Last time I ranted about one thing that is wrong with rrdtool.

It turns out that I, unfortunately, have more gripes to share. Let's talk today about the legend control.

The rrdtool's language for controlling how the graph is going to look and feel is pretty rich and complex. Among other things, it has a bunch of graphing commands that are able to manipulate the legend section of the graph. Some of those commands do nothing else, while the other commands only modify the legend as a side effect, and primarily exist for doing something else.

Let's take as an example the graph below:

rrdtool graph x.png
  --end 1235800000 --start end-150000
  'DEF:data=some.rrd:data:AVERAGE'
  'CDEF:sine=data,POP,1235800000,TIME,-,10000,/,SIN'
  'LINE1:sine#0000ff:a sine of foo\l'
  'CDEF:cosine=data,POP,1235800000,TIME,-,5000,/,COS'
  'LINE1:cosine#00ff00:a cosine of bar'

The trouble is that there is no instruction which can produce a so called "legend box" (a small blue box next to the "a sine of foo" legend text) without doing something else in the process. All of the commands that actually graph something can optionally produce a legend box, but there is no other way to make it.

If we extend our sine example with some nice downtime background (in Soviet Russia sines can have a downtime!), we get a nice picture like this:

rrdtool graph x.png
  --end 1235800000 --start end-150000
  'DEF:data=some.rrd:data:AVERAGE'
  'CDEF:downtime=data,0,0,IF,
    TIME,1235769489,GE,TIME,1235779489,LE,*,
    TIME,1235689489,GE,TIME,1235729489,LE,*,+,+'
  'CDEF:sine=data,POP,1235800000,TIME,-,10000,/,SIN'
  'LINE1:sine#0000ff:a sine of foo\l'
  'CDEF:cosine=data,POP,1235800000,TIME,-,5000,/,COS'
  'LINE1:cosine#00ff00:a cosine of bar\l'
  'TICK:downtime#ffe0e0:1.0:downtime'

But let's suppose that we'd also like to add background coloring for uptime, and indicate that in a legend. Let's use another CDEF for uptime, which will be just the opposite of our downtime CDEF:

rrdtool graph x.png
  --end 1235800000 --start end-150000
  'DEF:data=some.rrd:data:AVERAGE'
  'CDEF:downtime=data,0,0,IF,
    TIME,1235769489,GE,TIME,1235779489,LE,*,
    TIME,1235689489,GE,TIME,1235729489,LE,*,+,+'
  'CDEF:uptime=downtime,0,1,IF'
  'CDEF:sine=data,POP,1235800000,TIME,-,10000,/,SIN'
  'LINE1:sine#0000ff:a sine of foo\l'
  'CDEF:cosine=data,POP,1235800000,TIME,-,5000,/,COS'
  'LINE1:cosine#00ff00:a cosine of bar\l'
  'TICK:uptime#e0ffe0:1.0:uptime'
  'TEXTALIGN:left'
  'TICK:downtime#ffe0e0:1.0:downtime'

Oops. Of course. The graphing commands are processed in sequence, so the uptime "background" has obscured our actual sinusoidal data! We will have to put the uptime TICK before anything else to avoid this:

rrdtool graph x.png
  --end 1235800000 --start end-150000
  'DEF:data=some.rrd:data:AVERAGE'
  'CDEF:downtime=data,0,0,IF,
    TIME,1235769489,GE,TIME,1235779489,LE,*,
    TIME,1235689489,GE,TIME,1235729489,LE,*,+,+'
  'CDEF:uptime=downtime,0,1,IF'
  'CDEF:sine=data,POP,1235800000,TIME,-,10000,/,SIN'
  'TICK:uptime#e0ffe0:1.0:uptime'
  'LINE1:sine#0000ff:a sine of foo\l'
  'CDEF:cosine=data,POP,1235800000,TIME,-,5000,/,COS'
  'LINE1:cosine#00ff00:a cosine of bar\l'
  'TICK:downtime#ffe0e0:1.0:downtime'

See the problem? Now the legend boxes are not in the right order.

Naturally, it is pretty trivial to solve - we just remove the legend (it is optional) from the uptime TICK, and add another graphing command in the end with the right legend text. We'll simply have to make sure that this "graphing command" does not actually graph anything:

rrdtool graph x.png
  --end 1235800000 --start end-150000
  'DEF:data=some.rrd:data:AVERAGE'
  'CDEF:downtime=data,0,0,IF,
    TIME,1235769489,GE,TIME,1235779489,LE,*,
    TIME,1235689489,GE,TIME,1235729489,LE,*,+,+'
  'CDEF:uptime=downtime,0,1,IF'
  'CDEF:sine=data,POP,1235800000,TIME,-,10000,/,SIN'
  'TICK:uptime#e0ffe0:1.0'
  'LINE1:sine#0000ff:a sine of foo\l'
  'CDEF:cosine=data,POP,1235800000,TIME,-,5000,/,COS'
  'LINE1:cosine#00ff00:a cosine of bar\l'
  'TICK:uptime#e0ffe0:0.0:uptime'
  'TEXTALIGN:left'
  'TICK:downtime#ffe0e0:1.0:downtime'

Just like the last time - the problem is easily solvable, but it annoys me, since rrdtool again forces us to work against it instead of working with us. It would be nicer to have a way to put a legend box where we want it in some more direct way (maybe a variant of the COMMENT command)?