RRDTool::OO - Object-oriented interface to RRDTool
use RRDTool::OO; # Constructor my $rrd = RRDTool::OO->new( file => "myrrdfile.rdd" ); # Create a round-robin database $rrd->create( step => 1, # one-second intervals data_source => { name => "mydatasource", type => "GAUGE" }, archive => { rows => 5 }); # Update RRD with sample values, use current time. for(1..5) { $rrd->update($_); sleep(1); } # Start fetching values from one day back, # but skip undefined ones first $rrd->fetch_start(); $rrd->fetch_skip_undef(); # Fetch stored values while(my($time, $value) = $rrd->fetch_next()) { print "$time: ", defined $value ? $value : "[undef]", "\n"; } # Draw a graph in a PNG image $rrd->graph( image => "mygraph.png", vertical_label => 'My Salary', start => time() - 10, draw => { type => "area", color => '0000FF', legend => "Salary over Time", } );
RRDTool::OO is an object-oriented interface to Tobi Oetiker's round robin database tool rrdtool. It uses rrdtool's RRDs module to get access to rrdtool's shared library.
RRDTool::OO
RRDs
RRDTool::OO tries to marry rrdtool's database engine with the dwimminess and whipuptitude Perl programmers take for granted. Using RRDTool::OO abstracts away implementation details of the RRD engine, uses easy to memorize named parameters and sets meaningful defaults for parameters not needed in simple cases. For the experienced user, however, it provides full access to rrdtool's API. (Please check "Development Status" to verify how much of it has been implemented yet, though, since this module is under development :).
The constructor hooks up with an existing RRD database file $file, but doesn't create a new one if none exists. That's what the create() methode is for. Returns a RRDTool::OO object, which can be used to get access to the following methods.
$file
create()
Creates a new round robin database (RRD). A RRD consists of one or more data sources and one or more archives:
$rrd->create( step => 60, data_source => { name => "mydatasource", type => "GAUGE" }, archive => { rows => 5 });
This defines a RRD database with a step rate of 60 seconds in between primary data points. Additionally, the RRD start time can be specified by specifying a start parameter.
start
It also sets up one data source named my_data_source of type GAUGE, telling rrdtool to use values of data samples as-is, without additional trickery.
my_data_source
GAUGE
And it creates a single archive with a 1:1 mapping between primary data points and archive points, with a capacity to hold five data points.
The RRD's step parameter is optional, and will be set to 300 seconds by rrdtool by default.
step
In addition to the mandatory settings for name and type, data_source parameter takes the following optional parameters: min (minimum input, defaults to U), max (maximum input, defaults to U), heartbeat (defaults to twice the RRD's step rate).
name
type
data_source
min
U
max
heartbeat
Archives expect at least one parameter, rows indicating the number of data points the archive is configured to hold. If nothing else is set, rrdtool will store primary data points 1:1 in the archive.
rows
If you want to combine several primary data points into one archive point, specify values for cpoints (the number of points to combine) and cfunc (the consolidation function) explicitely:
cpoints
cfunc
$rrd->create( step => 60, data_source => { name => "mydatasource", type => "GAUGE" }, archive => { rows => 5, cpoints => 10, cfunc => 'AVERAGE', });
This will collect 10 data points to form one archive point, using the calculated average, as indicated by the parameter cfunc (Consolidation Function, CF). Other options for cfunc are MIN, MAX, and LAST.
MIN
MAX
LAST
If you're defining multiple data sources or multiple archives, just provide them in this manner:
# Define the RRD my $rc = $rrd->create( step => 60, data_source => { name => 'load1', type => 'GAUGE', }, data_source => { name => 'load2', type => 'GAUGE', }, archive => { rows => 5, cpoints => 10, cfunc => 'AVERAGE', }, archive => { rows => 5, cpoints => 10, cfunc => 'MAX', }, );
Update the round robin database with a new data sample, consisting of a value and an optional time stamp. If called with a single parameter, like in
$rrd->update($value);
then the current timestamp and the defined $value will be used. If update is called with a named parameter list like in
$value
update
$rrd->update(time => $time, value => $value);
then the given timestamp $time is used along with the given value $value.
$time
When updating multiple data sources, use the values parameter (instead of value) and pass an arrayref:
values
value
$rrd->update(time => $time, values => [$val1, $val2, ...]);
This way, rrdtool expects you to pass in the data values in exactly the same order as the data sources were defined in the create method. If that's not the case, then the values parameter also accepts a hashref, mapping data source names to values:
create
$rrd->update(time => $time, values => { $dsname1 => $val1, $dsname2 => $val2, ...});
RRDTool::OO will transform this automagically into RRDTool's template syntax.
RRDTool's
Initializes the iterator to fetch data from the RRD. This works nicely without any parameters if your archives are using a single consolidation function (e.g. MAX). If there's several archives in the RRD using different consolidation functions, you have to specify which one you want:
$rrd->fetch_start(cfunc => "MAX");
Other options for cfunc are MIN, AVERAGE, and LAST.
AVERAGE
fetch_start features a number of optional parameters: start, end and resolution.
fetch_start
end
resolution
If the start time parameter is omitted, the fetch starts 24 hours before the end of the archive. Also, an end time can be specified:
$rrd->fetch_start(start => time()-10*60, end => time());
The third optional parameter, resolution defaults to the highest resolution available and can be set to a value in seconds, specifying the time interval between the data samples extracted from the RRD. See the rrdtool fetch manual page for details.
rrdtool fetch
Development note: The current implementation fetches all values from the RRA in one swoop and caches them in memory. This might change in the future, to cache only the last timestamp and keep fetching from the RRD with every fetch_next() call.
fetch_next()
rrdtool doesn't remember the time the first data sample went into the archive. So if you run a rrdtool fetch with a start time of 24 hours ago and you've only submitted a couple of samples to the archive, you'll see many undef values.
undef
Starting from the current iterator position (or at the specified start time immediately after a fetch_start()), fetch_skip_undef() will skip all undef values in the RRA and positions the iterator right before the first defined value. If all values in the RRA are undefined, the a following $rrd->fetch_next() will return undef.
fetch_start()
fetch_skip_undef()
$rrd->fetch_next()
Gets the next row from the RRD iterator, initialized by a previous call to $rrd->fetch_start(). Returns the time of the archive point along with all values as a list.
$rrd->fetch_start()
If there's only one data source in the RRD, drawing a nice graph in an image file on disk is as easy as
$rrd->graph( image => $image_file_name, vertical_label => 'My Salary', draw => { thickness => 2, color => 'FF0000', legend => 'Salary over Time', }, );
This will assume a start time of 24 hours before now and an end time of now. Specify start and end explicitely to be clear:
$rrd->graph( image => $image_file_name, vertical_label => 'My Salary', start => time() - 24*3600, end => time(), draw => { thickness => 2, color => 'FF0000', legend => 'Salary over Time', }, );
As always, RRDTool::OO will pick reasonable defaults for parameters not specified. The values for data source and consolidation function default to the first values it finds in the RRD. If there are multiple datasources in the RRD or multiple archives with different values for cfunc, just specify explicitely which one to draw:
$rrd->graph( image => $image_file_name, vertical_label => 'My Salary', draw => { thickness => 2, color => 'FF0000', dsname => "load", cfunc => 'MAX'}, );
If draw doesn't define a type, it defaults to "line". If you don't want to define a type (because the graph shouldn't drawn), use type => "hidden". Other values are "area" for solid colored areas and "stack" for graphical values stacked on top of each other. And you can certainly have more than one graph in the picture:
draw
"line"
type => "hidden"
"area"
"stack"
$rrd->graph( image => $image_file_name, vertical_label => 'My Salary', draw => { type => 'area', color => 'FF0000', # red area dsname => "load", cfunc => 'MAX'}, draw => { type => 'stack', color => '00FF00', # a green area stacked on top of the red one dsname => "load", cfunc => 'AVERAGE'}, );
Graphs may assemble data from different RRD files. Just specify which file you want to draw the data from, using draw:
$rrd->graph( image => $image_file_name, vertical_label => 'Network Traffic', draw => { file => "file1.rrd", legend => "First Source", }, draw => { file => "file2.rrd", type => 'stack', color => '00FF00', # a green area stacked on top of the red one dsname => "load", legend => "Second Source", cfunc => 'AVERAGE' }, );
If a file parameter is specified per draw, the defaults for dsname and cfunc are fetched from this file, not from the file that's attached to the RRDTool::OO object $rrd used.
file
dsname
$rrd
Graphs may also consist of algebraic calculations of previously defined graphs. In this case, graphs derived from real data sources need to be named, so that subsequent cdef definitions can refer to them and calculate new graphs, based on the previously defined graph:
cdef
$rrd->graph( image => $image_file_name, vertical_label => 'Network Traffic', draw => { type => 'line', color => 'FF0000', # red line dsname => 'load', name => 'firstgraph', legend => 'Unmodified Load', }, draw => { type => 'line', color => '00FF00', # green line cdef => "firstgraph,2,*", legend => 'Load Doubled Up', }, );
Note that the second draw doesn't refer to a datasource dsname (nor does it fall back to the default data source), but defines a cdef, performing calculations on a previously defined draw named firstgraph. The calculation is specified using RRDTool's reverse polish notation, where instructions are separated by commas ("firstgraph,2,*" simply multiplies firstgraph's values by 2).
firstgraph
"firstgraph,2,*"
On a global level, in addition to the vertical_label parameter shown in the examples above, graph offers a plethora of parameters:
vertical_label
graph
vertical_label, title, start, end, x_grid, y_grid, alt_y_grid, no_minor, alt_y_mrtg, alt_autoscale, alt_autoscale_max, units_exponent, units_length, width, height, interlaced, imginfo, imgformat, overlay, unit, lazy, upper_limit, logarithmic, color, no_legend, only_graph, force_rules_legend, title, step.
title
x_grid
y_grid
alt_y_grid
no_minor
alt_y_mrtg
alt_autoscale
alt_autoscale_max
units_exponent
units_length
width
height
interlaced
imginfo
imgformat
overlay
unit
lazy
upper_limit
logarithmic
color
no_legend
only_graph
force_rules_legend
Some options (e.g. alt_y_grid) don't expect values, they need to be specified like
alt_y_grid => undef
in order to be passed properly to RRDTool.
The color option expects a reference to a hash with various settings for the different graph areas: back (background), canvas, shadea (left/top border), shadeb (right/bottom border), grid, mgrid major grid, font, frame and arrow:
back
canvas
shadea
shadeb
grid
mgrid
font
frame
arrow
$rrd->graph( ... color => { back => '#0e0e0e', arrow => '#ff0000', canvas => '#eebbbb', }, ... );
Please check the RRDTool documentation for a detailed description on what each option is used for:
http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/manual/rrdgraph.html
Sometimes it's useful to print max, min or average values of a given graph at the bottom of the chart or to STDOUT. That's what gprint and print options are for. In addition to the draw name (defaults to the first draw), a consolidation function can be specified: MIN, MAX, AVERAGE, LAST (defaults to AVERAGE). Note that this is unrelated to the data source's consolidation function, it's just applied on the graph print/gprint refer to. Finally, the format parameter gives a printf-like template (defaults to "Average=%lf": A call to
gprint
print
format
$rrd->graph( image => $image_file_name, draw => { name => "first_draw", dsname => "load", cfunc => 'MAX'}, gprint => { draw => 'first_draw', cfunc => 'AVERAGE', format => 'Average=%lf', }, );
prints "Average=x.xx" at the bottom of the graph, showing what the average value of the graph is.
Available as of rrdtool 1.0.49.
Dumps the RRD in XML format to STDOUT. If you want to dump it into a file instead, do this:
my $pid; unless ($pid = open DUMP, "-|") { die "Can't fork: $!" unless defined $pid; $rrd->dump(); exit 0; } waitpid($pid, 0); open OUT, ">out"; print OUT $_ for <DUMP>; close OUT;
Grabs the RRD's meta data and returns it as a hashref, holding a map of parameter names and their values.
Return the RRD's last update time.
Restore a RRD from a dump. The xml parameter specifies the name of the XML file containing the dump. If the optional flag range_check is set to a true value, restore will make sure the values in the RRAs do not exceed the limits defined for the different datasources:
dump
xml
range_check
restore
$rrd->restore(xml => "file.xml", range_check => 1);
Alter a RRD's data source configuration values:
# Set the heartbeat of the RRD's only datasource to 100 $rrd->tune(heartbeat => 100); # Set the minimum of DS 'load' to 1 $rrd->tune(dsname => 'load', minimum => 1); # Set the maximum of DS 'load' to 10 $rrd->tune(dsname => 'load', maximum => 10); # Set the type of DS 'load' to AVERAGE $rrd->tune(dsname => 'load', type => 'AVERAGE'); # Set the name of DS 'load' to 'load2' $rrd->tune(dsname => 'load', name => 'load2');
Return the message of the last error that occurred while interacting with RRDTool::OO.
The following methods are not yet implemented:
rrdresize, xport, rrdcgi.
rrdresize
xport
rrdcgi
By default, RRDTool::OO's methods will throw fatal errors (as in: they're calling die) if the underlying RRDs::* commands indicate failure.
die
RRDs::*
This behaviour can be overridden by calling the constructor with the raise_error flag set to false:
raise_error
my $rrd = RRDTool::OO->new( file => "myrrdfile.rdd", raise_error => 0, );
In this mode, RRDTool's methods will just pass back values returned from the underlying RRDs functions if an error happens (usually 1 if successful and undef if an error occurs).
RRDTool::OO is Log::Log4perl enabled, so if you want to know what's going on under the hood, just turn it on:
Log::Log4perl
use Log::Log4perl qw(:easy); Log::Log4perl->easy_init({ level => $DEBUG });
If you're interested particularily in rrdtool commands issued by RRDTool::OO while you're operating it, just enable the category "rrdtool":
"rrdtool"
Log::Log4perl->easy_init({ level => $INFO, category => 'rrdtool', layout => '%m%n', });
This will display all rrdtool commands that RRDTool::OO submits to the shared library. Let's turn it on for the code snippet in the SYNOPSIS section of this manual page and watch the output:
rrdtool
rrdtool create myrrdfile.rdd --step 1 \ DS:mydatasource:GAUGE:2:U:U RRA:MAX:0.5:1:5 rrdtool update myrrdfile.rdd N:1 rrdtool update myrrdfile.rdd N:2 rrdtool update myrrdfile.rdd N:3 rrdtool fetch myrrdfile.rdd MAX
Often handy for cut-and-paste.
RRDTool::OO requires a rrdtool installation with the RRDs Perl module, that comes with the rrdtool distribution.
Download the tarball from
http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/pub/rrdtool.tar.gz
and then unpack, compile and install:
tar zxfv rrdtool.tar.gz cd rrdtool-1.0.46 make cd perl-shared perl Makefile.PL ./configure make make test make install
Tobi Oetiker's RRDTool homepage at
http://rrdtool.org
especially the manual page at
http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/manual/index.html
My articles on rrdtool in "Linux Magazin" (Germany) and "Linux Magazine" (UK):
http://www.linux-magazin.de/Artikel/ausgabe/2004/06/perl/perl.html http://www.linux-magazine.com/issue/44/Limiting_Data.pdf (not online yet)
Mike Schilli, <m@perlmeister.com>
Copyright (C) 2004 by Mike Schilli
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.3 or, at your option, any later version of Perl 5 you may have available.
To install RRDTool::OO, copy and paste the appropriate command in to your terminal.
cpanm
cpanm RRDTool::OO
CPAN shell
perl -MCPAN -e shell install RRDTool::OO
For more information on module installation, please visit the detailed CPAN module installation guide.