Last time I spread some rrdtool love around. Love with no hate won't do, however. Taking a page from the way the BBC and many other news outlets cover certain conflicts, it seems prudent to present an unbiased view of rrdtool. And what better way to do that if not by spreading some hate this time?

Some time ago I had a task of adding background coloring to the portions of a graph, representing downtime of a device. This information was not available in the RRD archive itself, but could be obtained from elsewhere.

The information was in the form of epoch ranges, like this:

1235639489-1235646689,1235725889-1235729489

After some thought, I decided that making a CDEF with some simple RPN magic, in combination with a TICK graphing command would do the trick. The TICK command draws a vertical line of a specified height when a data point is not a zero or an UNKNOWN value, so I naïvely thought that this simple CDEF will achieve what I want (one long line here is split into several lines for your browsing convenience):

CDEF:downtime=0,TIME,1235639489,GE,
    TIME,1235646689,LE,*,
    TIME,1235725889,GE,
    TIME,1235729489,LE,*,+,+

The boolean values in rddtool's RPN are represented using the usual C-like convention (0 = false, 1 = true), so for any given time point the result of the CDEF above will be 0 if the point is outside any of the downtime intervals, 1 if it is inside one of the intervals, and more than 1 if it is inside several intervals (which should not happen, but is possible if we specify overlapping downtime epoch ranges).

If you did not understand how this is supposed to work, go read the rrdgraph_rpn manpage.

Anyway, that was easy enough, even if it was not very clean. So where is the promised hate, you'll ask? Here it is:

rrdtool graph x.png --end 1235800000 --start end-150000
    'DEF:data=some.rrd:someds:AVERAGE'
    'CDEF:downtime=0,TIME,1235639489,GE,TIME,1235646689,LE,*,
     TIME,1235725889,GE,TIME,1235729489,LE,*,+,+'
    'TICK:downtime#ffe0e0:1.0'

ERROR: rpn expressions without DEF or CDEF variables are not supported

You've read that right! Rrdtool insists that everything you put into a graph must ultimately come from some data source in some RRD archive. How stupid is that?

And the answer is - very stupid indeed, for at least two reasons.

First, it tries to pretend it knows what I might want to do better than me, and I really hate that in software. Whatever has happened to the idea that a tool must not get in the way of its user?

Secondly, this check is easily circumvented by adding a real DEF somewhere in the CDEF and then (mis)using RPN language to get rid of any value which comes from the DEF. There are many ways to do it, some more creative than others, but even this ham-fisted "solution" will do the job:

CDEF:downtime=data,0,0,IF,TIME,1235639489,GE,
    TIME,1235646689,LE,*,
    TIME,1235725889,GE,
    TIME,1235729489,LE,*,+,+

So we have a pointless restriction, and we are forced to work around it. Some might say that working against the tool to reach the goal is somehow challenging and maybe even fun. If you ask me, this is akin to programming in Brainfuck - a kind of activity better performed as a hobby, if that's your idea of how to spend your copious free time.

To rephrase the Perl's motto, rrdtool makes simple things hard.