Using VDEFs for set calculations in RRDTool

Introduction

The VDEF directive provides a mechanism for applying mathematical operations on sets of data.  Unlike the CDEF directive, the result of a VDEF is a single value.  The VDEF can reference either a DEF or CDEF data set and can perform a number of operations including calculating averages, standard deviations, least squares lines, and more.  These values can then be further referenced in CDEFs for graphing or printed out.

There is often much confusion regarding the differences of the DEF, CDEF, and VDEF directives.  It may help to think of the different directives in the following manner:

  • A DEF directive references a set of “raw” data as it is stored in a RRA
  • A CDEF directive applies a function to each data point it references
  • A VDEF directive applies a function to an aggregate of data points

The VDEF Directive

The basic format for a VDEF directive is as follows:

VDEF:Label=RPN Expression

Label is the name of the VDEF.  It may be referenced in other directives including HRULEs or CDEF calculations.  It may be from 1-19 characters long and consists of characters in the set [a-zA-Z0-9_].  Note that the label must be unique and cannot overlap with any labels assigned to other DEFs, CDEFs, or VDEFs.

RPN Expression is the mathematical or logical expression that is applied to a data set.  The expression uses Reverse Polish Notation to eliminate confusion or errors that may occur with the precedence rules required of traditional infix notation.  There are a number of mathematical, boolean and logical operators available for inclusion in a VDEF directive.

VDEF Examples

Example 1

This is a simple example which illustrates the use of VDEFs to reveal information about the set of data.  In this case, the MINIMUM, MAXIMUM, and AVERAGE operations are used to determine the respective values for the data set.  The resulting value for each operation is then used as the value for a HRULE providing a clear illustration in the resulting graph.  Note that the VDEF values are based only on the data referenced.  In this case, the data is bounded by the start and end time specified and so would likely differ for a different window into the original data set.

rrdtool graph "Example 1 VDEF.png" \
--start "end-48 hours" --end "12am Nov 1, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 1" \
--vertical-label "Temperature" \
DEF:temp=sysinfo.rrd:temperature:AVERAGE \
VDEF:min=temp,MINIMUM \
VDEF:max=temp,MAXIMUM \
VDEF:avg=temp,AVERAGE \
AREA:temp#FFEF00 \
HRULE:max#FF0000:"Max" \
HRULE:avg#000000:"Average" \
HRULE:min#0000FF:"Min"

Example 1 VDEF

Example 2

This example uses the average and standard deviation VDEF operations to identify temperature ranges that exceed the average temperature by more than one standard deviation.  The VDEF operations determine the appropriate values, which are then used in the CDEF operations to generate new data sets.  The original data set is graphed in the “hot” color with the “normal” and “cool” graphs overlayed on top of the appropriate sections.

The CDEF calculations may be difficult to parse for a novice to Reverse Polish syntax.  It may help to break it down as follows:

  1. cool=temp,avg,stdev,-,LE,temp,UNKN,IF
  2. cool=temp,(avg – stdev),LE,temp,UNKN,IF
  3. cool=(temp <= (avg – stdev)),temp,UNKN,IF
  4. cool=if (temp <= (avg – stdev)) then temp else UNKN

rrdtool graph "Example 2 VDEF.png" \
--start "end-48 hours" --end "12am Nov 1, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 2" \
--vertical-label "Temperature" \
DEF:temp=sysinfo.rrd:temperature:AVERAGE \
VDEF:avg=temp,AVERAGE \
VDEF:stdev=temp,STDEV \
CDEF:cool=temp,avg,stdev,-,LE,temp,UNKN,IF \
CDEF:medium=temp,avg,stdev,+,LE,temp,UNKN,IF \
AREA:temp#FF0000:"Hot" \
AREA:medium#FFEF00:"Normal" \
AREA:cool#0000FF:"Cool"

Example 2 VDEF

Example 3

This example illustrates how to use the least squares line VDEF operations to draw a trendline.  The LSLSLOPE operation can determine the slope of line and the LSLINT can provide the y-axis intercept value.  A trendline can then be generated using the classic "y=mx+b" formula (where m is the slope and b is the intercept).

The CDEF operation implements this formula using several “tricks” of rrdtool: a workaround for the CDEF requirement to reference a DEF or CDEF, and the use of the COUNT operation to increment a value for each data point in the graph set.  In the example, the CDEF reference requirement is satisfied by the “temp,POP” elements, which effectively puts a value from the temp DEF on the stack and then pops it back off, discarding it.

rrdtool graph "Example 3 VDEF.png" \
--start "end-48 hours" --end "12am Nov 1, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 3" \
--vertical-label "Temperature" \
DEF:temp=sysinfo.rrd:temperature:AVERAGE \
VDEF:slope=temp,LSLSLOPE \
VDEF:intercept=temp,LSLINT \
CDEF:trendline=temp,POP,COUNT,slope,*,intercept,+ \
AREA:temp#FFEF00 \
LINE2:trendline#000000

Example 3 VDEF

Example 4

This examples uses the PERCENTNAN operation in order to identify the 5% coolest and 5% hottest temperatures in the data set.  These values are then applied as part of the  CDEF calculations to generate the appropriate data sets for graphing.  Note that it is frequently best to use the PERCENTNAN operation instead of the PERCENT operation as the PERCENTNAN variant handles any gaps in the data in a more graceful manner.

rrdtool graph "Example 4 VDEF.png" \
--start "end-48 hours" --end "12am Nov 1, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 4" \
--vertical-label "Temperature" \
DEF:temp=sysinfo.rrd:temperature:AVERAGE \
VDEF:cool5=temp,5,PERCENTNAN \
VDEF:hot95=temp,95,PERCENTNAN \
CDEF:cool=temp,
cool5,LE,temp,UNKN,IF \
CDEF:medium=temp,
hot95,LE,temp,UNKN,IF \
AREA:temp#FF0000:"Hot" \
AREA:medium#FFEF00:"Normal" \
AREA:cool#0000FF:"Cool"

Example 4 VDEF

Using CDEFs to manipulate data in RRDTool

Introduction

The CDEF directive provides a means for manipulating the “raw” data stored in a round-robin archive (RRA).  It is typically used to apply a mathematical function to each data point referenced by one or more DEF statements which results in an array of new values — each of remains associated with the respective time of the original “raw” data point.  This is an in-memory transformation only; the original data remains unchanged in the RRA.

There is often much confusion regarding the differences of the DEF, CDEF, and VDEF directives.  It may help to think of the different directives in the following manner:

  • A DEF directive references a set of “raw” data as it is stored in a RRA
  • A CDEF directive applies a function to each data point it references
  • A VDEF directive applies a function to an aggregate of data points

The CDEF Directive

The basic format for a CDEF directive is as follows:

CDEF:Label=RPN Expression

Label is the name of the CDEF.  It may be referenced in other directives for inclusion in LINE, AREA charts or even other CDEF calculations.  It may be from 1-19 characters long and consists of characters in the set [a-zA-Z0-9_].  Note that the label must be unique and cannot overlap with any labels assigned to other DEFs, CDEFs, or VDEFs.

RPN Expression is the mathematical or logical expression that may be used to manipulate the raw data values as referenced by DEF or CDEF directives or even a pure mathematical function.  The expression uses Reverse Polish Notation to eliminate confusion or errors that may occur with the precedence rules required of traditional infix notation.  There are a number of mathematical, boolean and logical operators available for inclusion in a CDEF directive.

CDEF Examples

Example 1

This example illustrates the commonly used transformation of bytes to megabytes.  Disk and memory readings are often reported in bytes, but frequently this is not the most convenient unit for visualization.  In this case, the CDEF directive divides the “raw” data value as referenced by the DEF and divides it by 1048576 (1024 x 1024). Note that the AREA directive now references the CDEF label and that the vertical label has been updated to reflect the proper units.

rrdtool graph "Example 1 CDEF.png" \
--start "end-48 hours" --end "Dec 31, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 1" \
--vertical-label "Megabytes" \
DEF:disk1=sysinfo.rrd:disk_used:AVERAGE \
CDEF:megadisk1=disk1,1048576,/ \
AREA:megadisk1#0000FF:"Disk 1"

Example 1 CDEF

Example 2

This example shows a slightly more complex instance of the reverse-polish math that may be referenced in a CDEF.  In this case, the CDEF first sums up the the “raw” values as referenced by the two DEF statements and then converts the sum to megabytes.

rrdtool graph "Example 2 CDEF.png" \
--start "end-48 hours" --end "Nov 1, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 2" \
--vertical-label "Megabytes" \
DEF:disk1=sysinfo.rrd:disk_used:AVERAGE \
DEF:disk2=sysinfo.rrd:disk2_used:AVERAGE \
CDEF:megadisk=disk1,disk2,+,1048576,/ \
AREA:megadisk#0000FF:"Total Disk Used"

Example 2 CDEF

Example 3

This example illustrates a common technique for differentiating several types of related measurements.  It is a frequent graphing style for disk IO (reads vs. writes) as well as network IO (octets in vs. octets out).  It is achieved by simply negating the values of one of the operations and graphing the result.  In this example, a horizontal rule (HRULE) at the 0 point has also been added in order to highlight the baseline.  Note that the HRULE is specified as the last element to be drawn, which ensures that it will overlay the other graphed elements.

rrdtool graph "Example 3 CDEF.png" \
--start "end-48 hours" --end "Nov 1, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 3" \
--vertical-label "Bytes" \
DEF:read=sysinfo.rrd:bytes_read:AVERAGE \
DEF:write=sysinfo.rrd:bytes_written:AVERAGE \
CDEF:negwrite=0,write,- \
AREA:read#0000FF:"Bytes Read" \
AREA:negwrite#00FF00:"Bytes Written" \
HRULE:0#000000

Example 3 CDEF

Example 4

This is a more complex example which illustrates the use of the IF operation as well as a more advanced graphing style useful to call out anomalous behaviors.  In this case, the temperature values (referenced by the DEF “temp”) are first assessed by the LE (less than or equal to) and GT (greater than) operations.  The values assigned in these CDEFs (iscool, ishot) will then be used in the CDEFs with the IF operations.  The IF operations evaluate iscool/ishot and if it is “true” (i.e. not zero), then the value for temp is returned.  Otherwise, the special constant “unknown”  is returned.  These values for the cool/hot CDEFs are then graphed and result in a clear demarcation where the system is over-heated.

rrdtool graph "Example 4 CDEF.png" \
--start "end-48 hours" --end "Nov 1, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 4" \
--vertical-label "Temperature" \
DEF:temp=sysinfo.rrd:temperature:AVERAGE \
CDEF:iscool=temp,175,LE \
CDEF:ishot=temp,175,GT \
CDEF:cool=iscool,temp,UNKN,IF \
CDEF:hot=ishot,temp,UNKN,IF \
AREA:cool#0000FF:"cool" \
AREA:hot#FF0000:"hot"

Example 4 CDEF

Example 5

This example illustrates the use of the LIMIT operation to achieve a similar effect for highlighting anomalous conditions.  In this case, the entire data set is initially graphed using the “hot” color and then the “cool” data set is overlayed on top of the appropriate sections.

rrdtool graph "Example 5 CDEF.png" \
--start "end-48 hours" --end "12am Nov 1, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 5" \
--vertical-label "Temperature" \
DEF:temp=sysinfo.rrd:temperature:AVERAGE \
CDEF:cool=temp,0,175,LIMIT \
AREA:temp#FF0000:"hot" \
AREA:cool#0000FF:"cool"

Example 5 CDEF

Example 6

This example shows the use of the MIN operation to provide a “layer cake effect” in the graph.  This is a popular graphing technique that can be used either to signify a state change above a given threshold or simply to provide a color gradient in the graph for extra polish. This particular example again relies on overlaying the “cool” graph to mask out the relevant sections of the data.

rrdtool graph "Example 6 CDEF.png" \
--start "end-48 hours" --end "12am Nov 1, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 6" \
--vertical-label "Temperature" \
DEF:temp=sysinfo.rrd:temperature:AVERAGE \
CDEF:cool=temp,175,MIN \
AREA:temp#FF0000:"hot" \
AREA:cool#0000FF:"cool"

Example 6 CDEF

Rules, Legends and Scales with RRDTool

Introduction

This section covers some of the basic options and directives that can be used to personalize the graph.  There are a number of options available to control how the legends and other text are displayed, adjustments for the scaling behavior, as well as means for demarcating significant levels or marking points in time.

Rule Directives

Rules are simply straight lines that are drawn in the graphing area.  There are two variations:  Horizontal Rules (HRULEs) and Vertical Rules (VRULEs).  Typical usages of rules may include displaying a bar across the graph that may indicate an important threshold or a delimiter that reflects a system change.  Note that rules will not be drawn if they are not within the scope of the actual data ranges being displayed.  The general format for rules are as follows:

HRULE:Value#Color:Legend

VRULE:Time#Color:Legend

Value represents the value on the y-axis that will apply to a horizontal rule.  Note that horizontal rules can only be perfectly horizontal; it is not possible to supply a formula for a sloped line.  If the values of the data being displayed are not within the range of the horizontal line, then the line will not be displayed.  A frequent use of a HRULE is to demarcate a critical threshold in the data.

Time represents the value on the x-axis that will apply to a vertical rule.  The time must be presented as a standard Unix epoch value (number of seconds since Jan 1, 1970 UTC).  Note that if the time range of the data displayed does not contain the time specified for the VRULE, the rule will not be displayed.  A common use of a VRULE is to flag a “state change” in the measured systems, such as a new software release.

Color defines the color of the line or area graph.  This is expressed in the web-standard  RGB hexadecimal triplet and must be separated from the label by a ‘#’.  Example color definitions are: 333399 (blue), 33FF00 (bright green), and CC0000 (red).  If the color is not specified, then the area will be “invisible”.

Legend is the text associated with the legend entry for the graph.  It is an optional element, and if it is omitted the ‘:’ separator should also be omitted.

Rule Examples

Example 1

The following example is a simple example of the different rule types.  The HRULE specifies a red horizontal line drawn at the value of 750,000,000 on the y-axis.   The VRULE specifies a light green vertical line drawn at the value of 11:30am Dec 30, 2009 (1262201400 in Unix epoch format).

rrdtool graph "Example 1.png" \
--start "end-48 hours" --end "Dec 31, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 1" \
--vertical-label "Bytes" \
DEF:disk1=sysinfo.rrd:disk_used:AVERAGE \
AREA:disk1#0000FF:"Disk 1" \
HRULE:750000000#FF0000:"750 MB Warning" \
VRULE:1262201400#00FF00:"Software Rollout"

Example 1

Example 2

The following example illustrates use of a time value for the VRULE (Dec 18, 2009) that is not within the scope of the graphed data.  Note that the rule in this case is not displayed nor is there a legend element.  If the scope of the graphed data is changed to encompass the value of the VRULE, then the rule will again be displayed.  This behavior provides some utility in demarcating significant events without causing the y-axis to be “pinned” to a specified time.

rrdtool graph "Example 2 Rule.png" \
--start "end-48 hours" --end "Dec 31, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 2" \
--vertical-label "Bytes" \
DEF:disk1=sysinfo.rrd:disk_used:AVERAGE \
AREA:disk1#0000FF:"Disk 1" \
HRULE:750000000#FF0000:"750 MB Warning" \
VRULE:1261201400#00FF00:"Software Rollout"

Example 2

Legend and Title Options

--title specifies the text to be displayed above the graphing canvas.

--vertical-label specifies the text to be displayed next to the y-axis.  Typically, this indicates the units of the measurement.

--right-axis specifies an alternate y-axis scale that will be displayed on the right side of the graph.  This can be used to realign the units displayed which may have been adjusted to increase the legibility of the graph.  This parameter requires both a scale and offset (scale:offset) be specified.

--right-axis-label specifies the text to be displayed on the right axis.

--no-legend omits the legend information from being drawn.

--legend-position defines where the legend will be displayed in the graph.  Acceptable values are north, south, east and west.  The default value is south.

Legend and Title Examples

Example 1

This simple example illustrates the title, vertical-label, and legend-position parameters in use.  Note that the text for the label and title is quoted to ensure proper parsing.  The legend-position overrides the default value of south with east.

rrdtool graph "Example 1 Legend.png" \
--start "end-48 hours" --end "Dec 31, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 1" \
--vertical-label "Bytes" \
--legend-position east \
DEF:disk1=sysinfo.rrd:disk_used:AVERAGE \
AREA:disk1#0000FF:"Disk 1"

Example 1 Legend

Example 2

This example illustrates the use of the right-axis to specify an alternate scale.  In this case, the y-axis scale on the left (the default) reflects the CPU temperature measured in Celsius.  The y-axis scale on the right reflects the fan speed measured in RPM.  For this example, the scale has been set to 1 and the offset specified as 0.

rrdtool graph "Example 2 Legend.png" \
--start "end-48 hours" --end "Dec 31, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 2" \
--vertical-label "Celsius" \
--right-axis 1:0 \
--right-axis-label RPM \
DEF:temp=sysinfo.rrd:temperature:AVERAGE \
DEF:fan=sysinfo.rrd:cpu_fan:AVERAGE \
AREA:temp#0000FF:"CPU Temperature" \
LINE1:fan#00FF00:"Fan"

Example 2 Legend

Example 3

This example further refines the graph defined in Example 2 by adjusting the values of the fan so that they are closer to the range of the temperatures.  (This is performed by the CDEF directive, which will be further described in later examples.)  To keep the units correct, the scale for the right-label is adjusted to re-compensate.  Note that in this example the variations in temperature and RPM are now both clearly visible and the left and right scales on the y-axis reflect the different scales of the datatypes.

rrdtool graph "Example 3 Legend.png" \
--start "end-48 hours" --end "Dec 31, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 3" \
--vertical-label "Celsius" \
--right-axis 20:0 \
--right-axis-label RPM \
DEF:temp=sysinfo.rrd:temperature:AVERAGE \
DEF:fan=sysinfo.rrd:cpu_fan:AVERAGE \
CDEF:fan20=fan,20,/ \
AREA:temp#0000FF:"CPU Temperature" \
LINE1:fan20#00FF00:"Fan"

Example 3 Legend

Scale Options

--upper-limit provides an override of the default auto-scaling behavior by setting an explicit upper limit value for the y-axis.  Note that the value provided by this option will continue to be overridden if an actual data value in the graph exceeds the limit specified.

--lower-limit provides an override of the default auto-scaling behavior by setting an explicit lower limit value for the y-axis.  Note that the value provided by this option will continue to be overridden if an actual data value in the graph is lower than the limit specified.

--rigid is used in conjunction with the upper-limit and lower-limit options to provide a definitive maximum and minimum y-axis value.  With this option specified, the auto-scaling behavior will not adjust the scale even if a data value would exceed (or fall below) the upper or lower limits specified.

--logarithmic changes the y-axis to use a logarithmic scale instead of the default linear scale.  This can be useful to visualize fine-grain patterns in the data that may otherwise be obscured if the values are wide-ranging.

--units-exponent sets the exponent expressed in the y-axis scale to a fixed value.  For example, setting this to 3 would lead to the scale to consistently use units of 1000 (10^3).

--units-length defines how many characters rrdtool should assume are present in the y-axis scale labels.  This may be necessary to specify when deviating from the default values for the expression of the units (via the units-exponent, logarithmic, or units=si options) in order to prevent rrdtool from overlapping the vertical label and scale labels.

--units=si overrides the exponential notation with the standard SI unit symbols (k, M, etc.)  Note that the exponential notation is the default only for logarithmic graphs; linear graphs already use the SI notation.

Scale Examples

Example 1

This example illustrates the use of the upper and lower limit options.  Note that in this case the specified lower-limit is ignored, as an actual data value is lower than the value specified and so the auto-scaler adjusts the lower range of the scale to compensate.

rrdtool graph "Example 1 Scale.png" \
--start "end-1 month" --end "Dec 31, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 1" \
--vertical-label "Bytes" \
--upper-limit 1000000000 \
--lower-limit 500000000 \
DEF:disk1=sysinfo.rrd:disk_used:AVERAGE \
AREA:disk1#0000FF:"Disk"

Example 1 Scale

Example 2

This example demonstrates how the rigid option can be used to enforce the specified upper and lower limits.  Note that this strict adherence to the specified limits may prevent data that is out of range from being displayed.

rrdtool graph "Example 2 Scale.png" \
--start "end-1 month" --end "Dec 31, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 2" \
--vertical-label "Bytes" \
--upper-limit 1000000000 \
--lower-limit 500000000 \
--rigid \
DEF:disk1=sysinfo.rrd:disk_used:AVERAGE \
AREA:disk1#0000FF:"Disk"

Example 2 Scale

Example 3

In this example, the logarithmic option is specified to alter the y-axis scaling behavior.  The units-exponent is also specified which maintains the expression of the scale at the fixed rate of 10^3 (1000′s).

rrdtool graph "Example 3 Scale.png" \
--start "end-1 month" --end "Dec 31, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 3" \
--vertical-label "kilobytes" \
--logarithmic \
--units-exponent 3 \
DEF:disk1=sysinfo.rrd:disk_used:AVERAGE \
AREA:disk1#0000FF:"Disk"

Example 3 Scale

Example 4

This is an alternate view of the previous graph using the SI notation instead of the default exponential notation for a logarithmic graph.  In addition, the units-length option is specified to facilitate the alignment of the axis label and scale units.

rrdtool graph "Example 4 Scale.png" \
--start "end-1 month" --end "Dec 31, 2009" \
--imgformat PNG --width 500 --height 120 \
--title "Example 4" \
--vertical-label "Bytes" \
--logarithmic \
--units=si \
--units-length 5 \
DEF:disk1=sysinfo.rrd:disk_used:AVERAGE \
AREA:disk1#0000FF:"Disk"

Example 4 Scale