Initial revision
[rrdtool.git] / doc / rrdgraph.pod
1 =head1 NAME
2
3 rrdtool graph - Create a graph based on data from one or several RRD
4
5 =for html <div align="right"><a href="rrdgraph.pdf">PDF</a> version.</div> 
6
7 =head1 SYNOPSIS
8
9 B<rrdtool> B<graph> I<filename> 
10 S<[B<-s>|B<--start> I<seconds>]> 
11 S<[B<-e>|B<--end> I<seconds>]>
12 S<[B<-x>|B<--x-grid> I<x-axis grid and label>]>
13 S<[B<-y>|B<--y-grid> I<y-axis grid and label>]>
14 S<[B<--alt-y-grid>]>
15 S<[B<--alt-autoscale>]>
16 S<[B<--alt-autoscale-max>]>
17 S<[B<--units-exponent>]> I<value>]>
18 S<[B<-v>|B<--vertical-label> I<text>]>
19 S<[B<-w>|B<--width> I<pixels>]>
20 S<[B<-h>|B<--height> I<pixels>]> 
21 S<[B<-i>|B<--interlaced>]> 
22 S<[B<-f>|B<--imginfo> I<formatstring>]> 
23 S<[B<-a>|B<--imgformat> B<GIF>|B<PNG>]> 
24 S<[B<-z>|B<--lazy>]> 
25 S<[B<-o>|B<--logarithmic>]>
26 S<[B<-u>|B<--upper-limit> I<value>]> 
27 S<[B<-l>|B<--lower-limit> I<value>]>
28 S<[B<-g>|B<--no-legend>]>
29 S<[B<-r>|B<--rigid>]>
30 S<[B<--step> I<value>]>
31 S<[B<-b>|B<--base> I<value>]>
32 S<[B<-c>|B<--color> I<COLORTAG>B<#>I<rrggbb>]>
33 S<[B<-t>|B<--title> I<title>]>
34 S<[B<DEF:>I<vname>B<=>I<rrd>B<:>I<ds-name>B<:>I<CF>]>
35 S<[B<CDEF:>I<vname>B<=>I<rpn-expression>]>
36 S<[B<PRINT:>I<vname>B<:>I<CF>B<:>I<format>]>
37 S<[B<GPRINT:>I<vname>B<:>I<CF>B<:>I<format>]>
38 S<[B<COMMENT:>I<text>]>
39 S<[B<HRULE:>I<value>B<#>I<rrggbb>[B<:>I<legend>]]>
40 S<[B<VRULE:>I<time>B<#>I<rrggbb>[B<:>I<legend>]]>
41 S<[B<LINE>{B<1>|B<2>|B<3>}B<:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]]>
42 S<[B<AREA:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]]>
43 S<[B<STACK:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]]>
44
45 =head1 DESCRIPTION
46
47 The B<graph> functions main purpose is to create graphical
48 representations of the data stored in one or several B<RRD>s. Apart
49 from generating graphs, it can also extract numerical reports.
50
51 =over
52
53 =item I<filename> 
54
55 The name of the graph to generate. Since B<rrdtool> outputs
56 GIFs and PNGs, it's recommended that the filename end in either
57 F<.gif> or F<.png>.  B<rrdtool> does not enforce this, however.
58 If the  I<filename> is set to '-' the image file will be written
59 to standard out.  All other output will get suppressed.
60
61 PNG output is recommended, since it takes up to 40% less disk space
62 and 20-30% less time to generate than a GIF file.
63
64 If no graph functions are called, the graph will not be created.
65
66 =item B<-s>|B<--start> I<seconds> (default end-1day)
67
68 The time when the graph should begin. Time in seconds since
69 epoch (1970-01-01) is required. Negative numbers are relative to the
70 current time. By default one day worth of data will be graphed.
71 See also AT-STYLE TIME SPECIFICATION section in the I<rrdfetch>
72 documentation for a detailed explanation on how to specify time.
73
74 =item B<-e>|B<--end> I<seconds> (default now)
75
76 The time when the graph should end. Time in seconds since epoch.
77 See also AT-STYLE TIME SPECIFICATION section in the I<rrdfetch>
78 documentation for a detailed explanation of ways to specify time.
79
80 =item B<-x>|B<--x-grid> I<x-axis grid and label> (default autoconfigure)
81
82 The x-axis label is quite complex to configure. So if you don't have
83 very special needs, you can rely on the autoconfiguration to get this
84 right.
85
86 If you want no x-grid at all, use the magic setting B<none>.
87
88 The x-axis label and grid can be configured, using the following format:
89
90 I<GTM>B<:>I<GST>B<:>I<MTM>B<:>I<MST>B<:>I<LTM>:I<LST>B<:>I<LPR>B<:>I<LFM>
91
92 You have to configure three elements making up the x-axis labels and
93 grid. The base grid (I<G??>), the major grid (I<M??>) and the labels
94 (I<L??>). The configuration is based on the idea that you first
95 specify a well known amount of time (I<?TM>) and then say how many
96 times it has to pass between each grid line or label (I<?ST>). For the
97 label you have to define two additional items: The precision of the
98 label in seconds (I<LPR>) and the strftime format used to generate the
99 text of the label (I<LFM>).
100
101 The I<?TM> elements must be one of the following keywords: B<SECOND>,
102 B<MINUTE>, B<HOUR>, B<DAY>, B<WEEK>, B<MONTH> or B<YEAR>.
103
104 If you wanted a graph with a base grid every 10 minutes and a major
105 one every hour, with labels every hour you would use the following
106 x-axis definition.
107
108 C<MINUTE:10:HOUR:1:HOUR:1:0:%X>
109
110 The precision in this example is 0 because the %X format is exact. If
111 the label was the name of the day, we would have had a precision of 24
112 hours, because when you say something like 'Monday' you mean the whole
113 day and not Monday morning 00:00. Thus the label should be positioned
114 at noon. By defining a precision of 24 hours or rather 86400 seconds,
115 you make sure that this happens.
116
117 =item B<-y>|B<--y-grid> I<grid step>:I<label factor> (default autoconfigure)
118
119 Makes vertical grid lines appear at I<grid step> interval. Every
120 I<label factor> gridstep, a major grid line is printed, along with
121 label showing the value of the grid line.
122
123 If you want no y-grid at all set specify the magic word B<none>.
124
125 =item B<--alt-y-grid>
126
127 Place Y grid dynamically based on graph Y range. Algorithm ensures
128 that you always have grid, that there are enough but not too many
129 grid lines and the grid is metric. That is grid lines are placed 
130 every 1, 2, 5 or 10 units.  (contributed by Sasha Mikheev)
131
132
133 =item B<--alt-autoscale>
134
135 Compute Y range  based on function absolute minimum and 
136 maximum values. Default algorithm uses predefined set of ranges.  
137 This is good in many cases but it fails miserably when you need
138 to graph something like 260 + 0.001 * sin(x). Default algorithm 
139 will use Y range from 250 to 300 and on the graph you will see
140 almost straight line. With --alt-autoscale Y range will be
141 from slightly less the 260 - 0.001 to slightly more then 260 + 0.001
142 and periodic behavior will be seen.   (contributed by Sasha Mikheev)
143
144 =item B<--alt-autoscale-max>
145
146 Where --alt-autoscale will modify both the absolute maximum AND minimum
147 values, this option will only affect the maximum value. The minimum 
148 value, if not defined on the command line, will be 0. This option can
149 be useful when graphing router traffic when the WAN line uses compression,
150 and thus the throughput may be higher than the WAN line speed.
151
152 =item B<--units-exponent> I<value> (default autoconfigure)
153
154 This sets the 10**exponent scaling of the y-axis values.  Normally
155 values will be scaled to the appropriate units (k, M, etc.).  However
156 you may wish to display units always in k (Kilo, 10e3) even if the data
157 is in the M (Mega, 10e6) range for instance.  Value should be an
158 integer which is a multiple of 3 between -18 and 18 inclusive.  It is
159 the exponent on the units you which to use.  For example, use 3 to
160 display the y-axis values in k (Kilo, 10e3, thousands), use -6 to
161 display the y-axis values in u (Micro, 10e-6, millionths).  Use a value
162 of 0 to prevent any scaling of the y-axis values.
163
164 =item B<-v>|B<--vertical-label> I<text>
165
166 vertical label on the left side of the graph. This is normally used to
167 specify the units used.
168
169 =item B<-w>|B<--width> I<pixels> (default 400 pixel)
170
171 Width of the drawing area within the graph. This affects the size of the
172 gif.
173
174 =item B<-h>|B<--height> I<pixels> (default 100 pixel)
175
176 Width of the drawing area within the graph. This affects the size of the
177 gif.
178
179 =item B<-i>|B<--interlaced> (default: false)
180
181 If you set this option, then the resulting GIF will be interlaced.
182 Most web browsers display these incrementally as they load. If
183 you do not use this option, the GIFs default to being progressive
184 scanned. The only effect of this option is to control the format
185 of the GIF on disk. It makes no changes to the layout or contents
186 of the graph.
187
188 =item B<-f>|B<--imginfo> I<formatstring>
189
190 After the image has been created, the graph function uses printf
191 together with this format string to create output similar to the PRINT
192 function, only that the printf is supplied with the parameters
193 I<filename>, I<xsize> and I<ysize>. In order to generate an B<IMG> tag
194 suitable for including the graph into a web page, the command line
195 would look like this:
196
197  --imginfo '<IMG SRC="/img/%s" WIDTH="%lu" HEIGHT="%lu" ALT="Demo">'
198
199 =item B<-a>|B<--imgformat> B<GIF>|B<PNG> (default: GIF)
200
201 Allows you to produce PNG output from rrdtool. 
202
203 =item B<-z>|B<--lazy> (default: false)
204
205 Only generate the graph, if the current gif is out of date or not
206 existent.
207
208 =item B<-u>|B<--upper-limit> I<value> (default autoconfigure)
209
210 Defines the value normally located at the upper border of the
211 graph. If the graph contains higher values, the upper border will
212 move upwards to accomodate these values as well.
213
214 If you want to define an upper-limit which will not move in any
215 event you have to set the B<--rigid> option as well.
216
217 =item B<-l>|B<--lower-limit> I<value> (default autoconfigure)
218
219 This is not the lower limit of a graph.  But rather, this is the
220 maximum lower bound of a graph.  For example, the value -100 will
221 result in a graph that has a lower limit of -100 or less.  Use this
222 keyword to expand graphs down.
223
224 =item B<-r>|B<--rigid>
225
226 rigid boundaries mode.  Normally rrdgraph will automatically expand the
227 lower and upper limit if the graph contains a value outside the valid
228 range. With the r option you can disable this behavior
229
230 =item B<-b>|B<--base> I<value>
231
232 if you are graphing memory (and NOT network traffic) this switch
233 should be set to 1024 so that one Kb is 1024 byte. For traffic
234 measurement, 1 kb/s is 1000 b/s.
235
236 =item B<-o>|B<--logarithmic>
237
238 logarithmic y-axis scaling
239
240 =item B<-c>|B<--color> I<COLORTAG>B<#>I<rrggbb> (default colors)
241
242 override the colors for the standard elements of the graph. The I<COLORTAG>
243 must be one of the following symbolic names: B<BACK> ground, B<CANVAS>,
244 B<SHADEA> left/top border, B<SHADEB> right/bottom border, B<GRID>, B<MGRID>
245 major grid, B<FONT>, B<FRAME> and axis of the graph or B<ARROW>. This option
246 can be called multiple times to set several colors.
247
248 =item B<-g>|B<--no-legend>
249
250 Suppress generation of legend; only render the graph.
251
252 =item B<-t>|B<--title> I<text> (default no title)
253
254 Define a title to be written into the graph
255
256 =item B<--step> I<value> (default automatic)
257
258 By default rrdgraph calculates the width of one pixle in the time domain and
259 tries to get data at that resolution from the RRD. With this switch you can
260 override this behaviour. If you want rrdgraph to get data at 1 hour
261 resolution from the RRD, then you can set the step to 3600 seconds. Note,
262 that a step smaller than 1 pixle will be silently ignored.
263
264 =item B<DEF:>I<vname>B<=>I<rrd>B<:>I<ds-name>B<:>I<CF>
265
266 Define virtual name for a data source. This name can then be used
267 in the functions explained below. The
268 DEF call automatically chooses an B<RRA> which contains I<CF> consolidated data in a
269 resolution appropriate for the size of the graph to be drawn.  Ideally
270 this means that one data point from the B<RRA> should be represented
271 by one pixel in the graph.  If the resolution of the B<RRA> is higher
272 than the resolution of the graph, the data in the RRA will be further
273 consolidated according to the consolidation function (I<CF>) chosen.
274
275 =item B<CDEF:>I<vname>B<=>I<rpn-expression>
276
277 Create a new virtual data source by evaluating a mathematical expression,
278 specified in Reverse Polish Notation (RPN). If you have ever used a traditional
279 HP calculator you already know RPN. The idea behind RPN notation is, 
280 that you have a stack and push your data onto this stack. When ever
281 you execute an operation, it takes as many data values from the stack
282 as needed. The pushing of data is implicit, so when ever you specify a number
283 or a variable, it gets pushed automatically. 
284
285 If this is all a big load of incomprehensible words for you, maybe an
286 example helps (a more complete explanation is given in [1]): The
287 expression I<vname+3/2> becomes C<vname,3,2,/,+> in RPN. First the three
288 values get pushed onto the stack (which now contains (the current
289 value of) vname, a 3 and a 2).  Then the / operator pops two values
290 from the stack (3 and 2), divides the first argument by the second
291 (3/2) and pushes the result (1.5) back onto the stack. Then the +
292 operator pops two values (vname and 1.5) from the stack; both values
293 are added up and the result gets pushes back onto the stack. In the
294 end there is only one value left on the stack: The result of the
295 expression.
296
297 The I<rpn-expression> in the B<CDEF> function takes both, constant values
298 as well as I<vname> variables. The following operators can be used on these
299 values: 
300
301 =over
302
303 =item +, -, *, /, %
304
305 pops two values from the stack applies the selected operator and pushes 
306 the result back onto the stack. The % operator stands for the modulo
307 operation.
308
309 =item SIN, COS, LOG, EXP, FLOOR, CEIL
310
311 pops one value from the stack, applies the selected function and pushes
312 the result back onto the stack.
313
314 =item LT, LE, GT, GE, EQ
315
316 pops two values from the stack, compares them according to the selected
317 condition and pushes either 1 back onto the stack if the condition is true
318 and 0 if the condition was not true.
319
320 =item IF
321
322 pops three values from the stack. If the last value is not 0, the
323 second value will be pushed back onto the stack, otherwise the
324 first value is pushed back.
325
326 If the stack contains the values A, B, C, D, E are presently on the
327 stack, the IF operator will pop the values E D and C of the stack. It will
328 look at C and if it is not 0 it will push D back onto the stack, otherwise
329 E will be sent back to the stack.
330
331 =item MIN, MAX
332
333 selects the lesser or larger of the two top stack values respectively
334
335 =item LIMIT
336
337 replaces the value with I<*UNKNOWN*> if it is outside the limits specified
338 by the two values above it on the stack.
339
340  CDEF:a=alpha,0,100,LIMIT
341
342 =item DUP, EXC, POP
343
344 These manipulate the stack directly.  DUP will duplicate the top of the
345 stack, pushing the result back onto the stack.  EXC will exchange the top
346 two elements of the stack, and POP will pop off the top element of the
347 stack.  Having insufficient elements on the stack for these operations is
348 an error.
349
350 =item UN
351
352 Pops one value off the stack, if it is I<*UNKNOWN*>, 1 will be pushed
353 back otherwise 0.
354
355 =item UNKN
356
357 Push an I<*UNKNOWN*> value onto the stack.
358
359 =item PREV
360
361 Push I<*UNKNOWN*> if its at the first value of a data set or otherwise
362 the value of this CDEF at the previous time step. This allows you to
363 perform calculations across the data.
364
365 =item INF, NEGINF
366
367 Push a positive or negative infinite (oo) value onto the stack. When
368 drawing an infinite number it appears right at the top or bottom edge of the
369 graph, depending whether you have a positive or negative infinite number.
370
371 =item NOW
372
373 Push the current (real world) time onto the stack.
374
375 =item TIME
376
377 Push the time the current sample was taken onto the stack. This is the
378 number of non-skip seconds since 0:00:00 January 1, 1970.
379
380 =item LTIME
381
382 This is like TIME B<+ current timezone offset in seconds>. The current
383 offset takes daylight saving time into account, given your OS supports
384 this. If you were looking at a sample, in Zurich, in summer, the
385 offset would be 2*3600 seconds, as Zurich at that time of year is 2
386 hours ahead of UTC.
387
388 Note that the timezone offset is always calculated for the time the
389 current sample was taken at. It has nuthing todo with the time you are
390 doing the calculation.
391
392 =back
393
394 Please note that you may only use I<vname> variables that you
395 previously defined by either B<DEF> or B<CDEF>. Furthermore, as of
396 this writing (version 0.99.25), you must use at least one I<vname>
397 per expression, that is "CDEF:fourtytwo=2,40,+" will yield an error
398 message but not a I<vname> fourtytwo that's always equal to 42.
399
400 =item B<PRINT:>I<vname>B<:>I<CF>B<:>I<format>
401
402 Calculate the chosen consolidation function I<CF> over the data-source
403 variable I<vname> and C<printf> the result to stdout using I<format>.
404 In the I<format> string there should be a '%lf' or '%le' marker in the
405 place where the number should be printed.
406
407 If an additional '%s' is found AFTER the marker, the value will be scaled
408 and an appropriate SI magnitude unit will be printed in place of the '%s'
409 marker. The scaling will take the '--base' argument into consideration!
410
411 If a '%S' is used instead of a '%s', then instead of calculating the
412 appropriate SI magnitude unit for this value, the previously calculated
413 SI magnitude unit will be used.  This is useful if you want all the values
414 in a PRINT statement to have the same SI magnitude unit.  If there was
415 no previous SI magnitude calculation made, then '%S' behaves like a '%s',
416 unless the value is 0, in which case it does not remember a SI magnitude
417 unit and a SI magnitude unit will only be calculated when the next '%s' is
418 seen or the next '%S' for a non-zero value.
419
420 If you want to put a '%' into your PRINT string, use '%%' instead.
421
422 =item B<GPRINT:>I<vname>B<:>I<CF>B<:>I<format>
423
424 Same as B<PRINT> but the result is printed into the graph below the legend.
425
426 =back
427
428 B<Caveat:> When using the B<PRINT> and B<GRPRINT> functions to
429 calculate data summaries over time periods bounded by the current
430 time, it is important to note that the last sample will almost always
431 yield a value of UNKNOWN as it lies after the last update time.  This
432 can result in slight data skewing, particularly with the B<AVERAGE>
433 function.  In order to avoid this, make sure that your end time is at
434 least one heartbeat prior to the current time.
435
436 =over
437
438
439 =item B<COMMENT:>I<text>
440
441 Like B<GPRINT> but the I<text> is simply printed into the graph.
442
443 =item B<HRULE:>I<value>B<#>I<rrggbb>[B<:>I<legend>]
444
445 Draw a horizontal rule into the graph and optionally add a legend
446
447 =item B<VRULE:>I<time>B<#>I<rrggbb>[B<:>I<legend>]
448
449 Draw a vertical rule into the graph and optionally add a legend
450
451 =item B<LINE>{B<1>|B<2>|B<3>}B<:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]
452
453 Plot for the requested data, using the color specified. Write a legend
454 into the graph. The 3 possible keywords B<LINE1>, B<LINE2>, and B<LINE3> 
455 generate increasingly wide lines. If no color is defined, 
456 the drawing is done 'blind' this is useful in connection with the 
457 B<STACK> function when you want to ADD the values of two 
458 data-sources without showing it in the graph.
459
460 =item B<AREA>:I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]
461
462 Does the same as B<LINE?>, but the area between 0 and 
463 the graph will be filled with the color specified.
464
465 =item B<STACK>:I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]
466
467 Does the same as B<LINE?>, but the graph gets stacked on top of the previous
468 B<LINE?>, B<AREA> or B<STACK> graph. Depending on the type of the
469 previous graph, the B<STACK> will be either a B<LINE?> or an B<AREA>.
470 This obviously implies that the first B<STACK> must be preceded by an
471 B<AREA> or B<LINE?> -- you need something to stack something onto in
472 the first place ;) 
473
474 Note, that when you STACK onto *UNKNOWN* data, rrdtool will not draw
475 any graphics ... *UNKNOWN* is not zero ... if you want it to zero
476 then you might want to use a CDEF argument with IF and UN functions to
477 turn *UNKNOWN* into zero ...
478
479 =back
480
481 =head1 NOTES on legend arguments
482
483 =head2 Escaping the colon
484
485 In a ':' in a I<legend> argument will mark the end of the legend. To
486 enter a ':' into a legend, the colon must be escaped with a backslash '\:'.
487 Beware, that many environments look for backslashes themselves, so it may
488 be necessary to write two backslashes so that one is passed onto rrd_graph.
489
490 =head2 String Formatting
491
492 The text printed below the actual graph can be formated by appending special
493 escaped characters at the end of a text. When ever such a character occurs,
494 all pending text is pushed onto the graph according to the character
495 specified.
496
497 Valid markers are: B<\j> for justified, B<\l> for left aligned, B<\r> for
498 right aligned and B<\c> for centered. In the next section there is an
499 example showing how to use centered formating.
500
501 Normally there are two space characters inserted between every two items
502 printed into the graph. The space following a string can be suppressed by
503 putting a B<\g> at the end of the string. The B<\g> also squshes any space
504 inside the string if it is at the very end of the string. This can be used
505 in connection with B<%s> to supress empty unit strings.
506
507  GPRINT:a:MAX:%lf%s\g
508
509 A special case is COMMENT:B<\s> this inserts some additional vertical space
510 before placing the next row of legends.
511
512 =head1 NOTE on Return Values
513
514 Whenever rrd_graph gets called, it prints a line telling the size of
515 the gif it has just created to STDOUT. This line looks like this: XSIZExYSIZE.
516
517 =head1 EXAMPLE 1
518
519   rrdtool graph demo.gif --title="Demo Graph" \
520           DEF:cel=demo.rrd:exhaust:AVERAGE \
521           "CDEF:far=cel,1.8,*,32,+"" \
522           LINE2:cel#00a000:"D. Celsius" \
523           LINE2:far#ff0000:"D. Fahrenheit\c"
524
525 =head1 EXAMPLE 2
526
527 This example demonstrates the syntax for using IF and UN to set
528 I<*UNKNOWN*> values to 0.  This technique is useful if you are
529 aggregating interface data where the start dates of the data sets
530 doesn't match.
531
532   rrdtool graph demo.gif --title="Demo Graph" \
533          DEF:idat1=interface1.rrd:ds0:AVERAGE \
534          DEF:idat2=interface2.rrd:ds0:AVERAGE \
535          DEF:odat1=interface1.rrd:ds1:AVERAGE \
536          DEF:odat2=interface2.rrd:ds1:AVERAGE \
537          CDEF:agginput=idat1,UN,0,idat1,IF,idat2,UN,0,idat2,IF,+,8,* \
538          CDEF:aggoutput=odat1,UN,0,odat1,IF,odat2,UN,0,odat2,IF,+,8,* \
539          AREA:agginput#00cc00:Input Aggregate \
540          LINE1:agginput#0000FF:Output Aggregate
541          
542 Assuming that idat1 has a data value of I<*UNKNOWN*>, the CDEF expression 
543
544  idat1,UN,0,idat1,IF 
545
546 leaves us with a stack with contents of 1,0,NaN and the IF function
547 will pop off the 3 values and replace them with 0.  If idat1 had a
548 real value like 7942099, then the stack would have 0,0,7942099 and the
549 real value would be the replacement.  
550
551 =head1 EXAMPLE 3
552
553 This example shows two ways to use the INF function. First it makes
554 the background change color during half of the hours. Then, it uses
555 AREA and STACK to draw a picture. If one of the inputs was UNKNOWN,
556 all inputs are overlaid with another AREA.
557
558   rrdtool graph example.png --title="INF demo" \
559          DEF:val1=some.rrd:ds0:AVERAGE \
560          DEF:val2=some.rrd:ds1:AVERAGE \
561          DEF:val3=some.rrd:ds2:AVERAGE \
562          DEF:val4=other.rrd:ds0:AVERAGE \
563          CDEF:background=val4,POP,TIME,7200,%,3600,LE,INF,UNKN,IF \
564          CDEF:wipeout=val1,val2,val3,val4,+,+,+,UN,INF,UNKN,IF \
565          AREA:background#F0F0F0 \
566          AREA:val1#0000FF:Value1 \
567          STACK:val2#00C000:Value2 \
568          STACK:val3#FFFF00:Value3 \
569          STACK:val4#FFC000:Value4 \
570          AREA:wipeout#FF0000:Unknown
571
572 The first CDEF uses val4 as a dummy value. It's value is removed immediately
573 from the stack. Then a decision is made based on the time that a sample was
574 taken. If it is an even hour (UTC time !) then the area will be filled. If
575 it is not, the value is set to UNKN and is not plotted.
576
577 The second CDEF looks if any of val1,val2,val3,val4 is unknown. It does so by
578 checking the outcome of sum(val1,val2,val3,val4). Again, INF is returned when
579 the condition is true, UNKN is used to not plot the data.
580
581 The different items are plotted in a particular order. First do the background, then use a
582 normal area to overlay it with data. Stack the other data until they are all plotted. Last but
583 not least, overlay everything with eye-hurting red
584 to signal any unknown data.
585
586 Note that this example assumes that your data is in the positive half of the y-axis
587 otherwhise you would would have to add NEGINF in order to extend the coverage
588 of the rea to whole graph.
589
590 =head1 AUTHOR
591
592 Tobias Oetiker E<lt>oetiker@ee.ethz.chE<gt>
593
594 =head1 REFERENCES
595
596 [1] http://www.dotpoint.com/xnumber/rpn_or_adl.htm