PHP RRDTool tutorial

On a number of occasions I've used RRDTool to graph network traffic and the like. A few years ago when I started using cacti I started wondering how to make the graphs myself. Creating the graphs on the command line isn't that hard once you know how to set things up and it turns out doing the same in PHP is just as easy.

For this tutorial I'm going to assume you understand how to get RRDTool installed and working from the command line. If not you should take a look at this tutorial (if you are in a hurry look at the "A Real World Example" section) or any of the tutorials on this page.

Setup and introduction

You need to have PHP compiled with RRDTool support to run the following PHP examples. If you compile PHP by hand then see: how to build the php rrdtool extension by hand. If you are using a distribution's pre-compiled PHP binary you should be able to install a second package with RRDTool support. You can verify that your PHP install is ready to go by running this:

<?php
phpinfo(INFO_MODULES);
?>

Then search for "rrdtool" in the output and make sure that "rrdtool support" is enabled.

While going through each of the following steps you will notice that each call takes a couple of parameters and then one parameter that is just a string of options. The string of options is exactly how it is for generating/updating/graphing RRDs from the command line. This makes for a consistent interface for the different languages that have RRDTool support.

Creating a RRD

We first need to create a database for our data. For these examples I will be creating a database that could be used for generating network graphs. This database is created for updates every 5 minutes (300 seconds), has input and output counters that store data for the average and max counts and stores enough samples for hourly, daily, monthly and yearly graphs of both average and max.

<?php

  $fname = "net.rrd";

  $opts = array( "--step", "300", "--start", 0,
           "DS:input:COUNTER:600:U:U",
           "DS:output:COUNTER:600:U:U",
           "RRA:AVERAGE:0.5:1:600",
           "RRA:AVERAGE:0.5:6:700",
           "RRA:AVERAGE:0.5:24:775",
           "RRA:AVERAGE:0.5:288:797",
           "RRA:MAX:0.5:1:600",
           "RRA:MAX:0.5:6:700",
           "RRA:MAX:0.5:24:775",
           "RRA:MAX:0.5:288:797"
        );

  $ret = rrd_create($fname, $opts, count($opts));

  if( $ret == 0 )
  {
    $err = rrd_error();
    echo "Create error: $err\n";
  }
?>

After running you will have a file called net.rrd in the current directory. This is your RRD and will contain all the samples for your graphs.

For more information on the options to rrd_create see: rrdcreate

Updating a RRD

The next step is to update your RRD on the frequency you set when you created it. In the case above the frequency was set to 5 minutes (300 seconds). The following script generates random input and output values as input to the update function, sleeps for 300 seconds and then loops.

<?php

  $fname = "net.rrd";

  $total_input_traffic = 0;
  $total_output_traffic = 0;

  while(true)
  {
    $total_input_traffic += rand(10000, 15000);
    $total_output_traffic += rand(10000, 30000);

    echo time() . ": " . $total_input_traffic . " and " . $total_output_traffic . "\n";

    $ret = rrd_update($fname, "N:$total_input_traffic:$total_output_traffic");

    if( $ret == 0 )
    {
      $err = rrd_error();
      echo "ERROR occurred: $err\n";
    }

    sleep(300);
  }
?>

Your input and output values could be pulled from anywhere here, I just wanted to have a source that would work for anyone who wanted to try the script.

After letting this script run for a few hours you can run the following shell script to see what type of data you have collected so far:

For more information on the options to rrd_update here: rrdupdate

#!/bin/sh
END=`date +%s`
START=`echo $END-3600|bc` # over the hour
rrdtool fetch net.rrd AVERAGE --start $START --end $END

That should display the average sample values for the last hour.

Displaying RRD data as a graph

Now that you have data in your RRD you will want to graph it. The following code will graph the average input and output for 1 day as well as the max for that day.

<?php

  $opts = array( "--start", "-1d", "--vertical-label=B/s",
                 "DEF:inoctets=net.rrd:input:AVERAGE",
                 "DEF:outoctets=net.rrd:output:AVERAGE",
                 "AREA:inoctets#00FF00:In traffic",
                 "LINE1:outoctets#0000FF:Out traffic\\r",
                 "CDEF:inbits=inoctets,8,*",
                 "CDEF:outbits=outoctets,8,*",
                 "COMMENT:\\n",
                 "GPRINT:inbits:AVERAGE:Avg In traffic\: %6.2lf %Sbps",
                 "COMMENT:  ",
                 "GPRINT:inbits:MAX:Max In traffic\: %6.2lf %Sbps\\r",
                 "GPRINT:outbits:AVERAGE:Avg Out traffic\: %6.2lf %Sbps",
                 "COMMENT: ",
                 "GPRINT:outbits:MAX:Max Out traffic\: %6.2lf %Sbps\\r"
               );

  $ret = rrd_graph("net_1d.gif", $opts, count($opts));

  if( !is_array($ret) )
  {
    $err = rrd_error();
    echo "rrd_graph() ERROR: $err\n";
  }
?>

You should end up with a file named net_1d.gif in your working directory that looks something like:

You can also do weekly and monthly graphs by changing the start parameter to -1w or -1m:

For the impatient you can download my net.rrd file and try the graphs for yourself.

See the other tutorials for more information on the options you have for graphing.

For more information on the options to rrd_graph see: rrdgraph

Tags: , ,

23 thoughts on “PHP RRDTool tutorial

  1. passerby

    Seems nice, makes the graph and all but doesnt update any info? Graph available for download also didnt not show any info, with script to check provided.

    — copy as . due to some funky stuff on this site.

  2. passerby

    Just to update before the prev post gets approved it seems to work, it was just reading a weird cache copy, changed a few names and all is good.

    Please make a note on the — (double dashes) copying over as . (periods), was a little weird.

  3. Pingback: Akismet spam graphs with PHP RRD @ IONCANNON

  4. Sébastien Cramatte

    Does anyone know how can I made a raw output directly in PHP without generate the image file on the disk ?

    I've tried to put '-' as filename and effectively no file is generated … but I don't know how can I get the output …

    # this code doesn't work because rrd_graph return an array but no raw datas …

    header('Content-type: image/png');

    echo rrd_graph("-", $opts, count($opts);

  5. Sam

    There's an rrd_fetch function included with the library as well, but I cannot for the life of me get it to work. This should work:

    rrd_fetch("basic.rrd",array("MAX"),1);

    But it just spits back null. If I add any arguments (like a start time), I get a seg fault. e.g.

    rrd_fetch("basic.rrd",array("MAX","-s","now-1hr"),3);

    Anyone got any insights in to this?

  6. kulaba james

    thanks for that work. but how do I use RRDtool to monitor the hard disk usage.\

    thanks

  7. Fritz

    The rrdtool extension works great with the apache php module through a web browser. But if I try to use any of the rrd functions from the php-cli command line php, I get a segmentation fault.

    Any ideas/advice?

  8. Novae

    Is there any way to force it to make png's instead of gifs. I'd like to use some custom fonts but ttf support is only available in png's.

    cheers, Novae.

  9. Fritz

    I have noticed another problem with rrd_graph. When operating on the same datafile, with the same exact parameters, I refresh the page 4 times and get 4 slightly different graphs.

    If I refresh 12 times, I get the same 4 graphs in the same sequence over and over 3 times.

    If I keep refreshing the browser, It continues to cycle through the same 4 graphs… same parameters… same rrd file.

    Any idea what's going on? I've been trying to figure it out all day.

  10. Florian

    Excellent tutorial ! If you are providing random values to your rrd database using scripts or whatever, also make sure that when you call rrd_graph you pass the –start and –end arguments correctly. I spent some hours understanding why nothing was graphed while the RRD was correct. Hope that helps.

  11. Marcin

    Well it is very good indeed but could you also add how to put on the Graph total sum up of incoming/outgoing traffic? It would be very helpful as many people ask about this. Thank you.

  12. carson Post author

    @Marcin

    You would want to use the rrd_fetch call to do that. Something like this:

    $opts = array( "AVERAGE", "–start", "-1d" );
    $ret = rrd_fetch("net.rrd", $opts, count($opts));

    Then iterate over the returned values and sum them up in code. After that you can just print the value along with all the other values in the rrd_graph call.

  13. Peter

    Hi,

    thx for excellent tutorial.

    I have question:

    Is it possible to make network graph (based on netacct-mysql) with 5min average?

    Thx

  14. Pingback: Installing RRDTool for PHP on Ubuntu Server

  15. Luigi Rosa

    Under CentOS/64 the rrd_create() function returned "can't parse argument '\x96step'" error.

    I solved it calling the function in this way:

    $opts = array( chr(45).chr(45)."step", "900", chr(45).chr(45)."start", 0,

    and so on.

  16. Joe Linux

    Hi,

    The extension build fine, but when i tried this example i got the following error :


    Create error: can't parse argument 'net.rrd'

    If anyone has an idea… seems there's something weird in the API… Something related to my versions ? RRDtool 1.3.1 and PHP 5.2.5, and i'm on a 64-bits (AMD) plateform.

    Thanks for any help,
    regards,

  17. Soule

    Hello,

    I've been following your fine tutorial from the start. I'm running Ubuntu server 8.04, I've installed the RRDtool extention and copied the first script you published –
    but I get this error:

    Create error: can't parse argument '–step'

    Can you help me? For the record, i installed from ubuntu repository librrd-dev and did the rest manually, and on phpinfo() it says rrdtool 1.2x.

    Cheers,

    -Soule

  18. carson Post author

    @Soule You probably want to make sure that the step has two dashes in front of it and not one long dash. Depending on the day the double dashes get changed into one long dash by wordpress and make things fail.

  19. tarek

    Hi and thanks for this tutorial, i had some trouble with php and rrdtool and i got this error : rrd_graph() ERROR: unknown option '1' when i try to run your exemple, do you know how to fix that?

    Regards.

  20. carson Post author

    @tarek Make sure the options that need a double dash haven't been converted into the special long dash. For instance, the first value in the opts should have two dashes in front of it.

  21. Reid Nicholson

    Had a problem with the php-rrdtool RPM on a Centos5.x server. The RPM didn't add the file "rrdtool.ini" to the "/etc/php.d/" directory. Added the file with the following 2 lines:
    ; Enable rrdtool extension module
    extension=rrdtool.so

    restarted httpd and the module loaded.

Leave a Reply

Your email address will not be published. Required fields are marked *