E-Scribe : a programmer’s blog

About Me

PBX I'm Paul Bissex. I build web applications using open source software, especially Django. Started my career doing graphic design for newspapers and magazines in the '90s. Then wrote tech commentary and reviews for Wired, Salon, Chicago Tribune, and others you never heard of. Then I built operations software at a photography school. Then I helped big media serve 40 million pages a day. Then I worked on a translation services API doing millions of dollars of business. Now I'm building the core platform of a global startup accelerator. Feel free to email me.


I co-wrote "Python Web Development with Django". It was the first book to cover the long-awaited Django 1.0. Published by Addison-Wesley and still in print!


Built using Django, served with gunicorn and nginx. The database is SQLite. Hosted on a FreeBSD VPS at Johncompanies.com. Comment-spam protection by Akismet.


Pile o'Tags

Stuff I Use

Bitbucket, Debian Linux, Django, Emacs, FreeBSD, Git, jQuery, LaunchBar, macOS, Markdown, Mercurial, Python, S3, SQLite, Sublime Text, xmonad

Spam Report

At least 237138 pieces of comment spam killed since 2008, mostly via Akismet.

Visualizing trends in the bug-tracker

At work I manage projects with Trac. It's great. We have about ten different projects, including websites and internal web apps, with most of the code in a central Subversion repository hooked up to Trac so that it's easy to see what got changed when (and why!).

But rather than bore you with Trac evangelism I'll share a goofy hack I built to get a basic visualization of the ticket load in Trac over time.

This is possibly the weirdest little hack I've ever shared publicly.

First, the stats-gathering. The data lives in a text file; actually, a YAML file. I chose YAML because at first the idea of graphing was only a "might-do" and I wanted to have a text file I could read. The file is updated by a shell script like this running as a nightly cronjob:

echo '-'
echo '  date  : `date +'%Y-%m-%d`'
echo 'SELECT "  high  : " || count(*) FROM ticket WHERE \
  priority="high" AND status!="closed";' | sqlite3 /var/db/trac.db
echo 'SELECT "  medium: " || count(*) FROM ticket WHERE \
  priority="medium" AND status!="closed";' | sqlite3 /var/db/trac.db
echo 'SELECT "  low   : " || count(*) FROM ticket WHERE \
  priority="low" AND status!="closed";' | sqlite3 /var/db/trac.db

Next, the graphing code. Be thankful I didn't go all the way to making this a one-liner.

import yaml, urllib
url = "http://example.edu/stuff/trac_stats.txt"
data = yaml.load(urllib.urlopen(url).read())
print "\n".join("%s %s%s%s" % 
    (d['date'], "!"*d['high'], "*"*d['medium'], "."*d['low'])
    for d in data)

Finally, here's what the output looks like -- the three different characters in the bars represent high, medium, and low priority tickets respectively.

2008-01-09 !!!!!!!!!!************************...................
2008-01-10 !!!!!!!!************************........................
2008-01-11 !!!**************************.......................

Rendering sparkline graphs via the Google Chart API is left as an exercise for the reader.

Saturday, January 12th, 2008

0 comments pending approval
Comments are closed for this post. But I welcome questions/comments via email or Twitter.