1

Thanks in advance for your time and effort. This is my first script with PHP and RRD's. While I was writing a short program for SNMP I came across with RRD a powerful tool for graphical output. I tried to wright a short operating script to imitate the output of a graph. I read as much as possible documentations regarding RRD from the official page and tried to add them to my PHP code. I have found some functions while I was trying to debug my code which are showing that my data are coming in normally and cased on reference as expected. Sample provided under:

["last_update"]=>
int(1396917542)
["ds_cnt"]=>
int(3)
["ds_navm"]=>
array(3) {
  [0]=>
  string(10) "ifInOctets"
  [1]=>
  string(11) "ifOutOctets"
  [2]=>
  string(9) "sysUpTime"
}
["data"]=>
array(3) {
  [0]=>
  string(4) "1405"
  [1]=>
  string(4) "1219"
  [2]=>
  string(4) "1893"
 }
}

Based on function:

"$debug = rrd_lastupdate (
                          "".$rrdFile.""
             );"

I am having difficulties to understand since the input is coming correctly and there is not print error displayed while compiling my code why I do not get any output?

I have included my working code as example for possible reproduction and better understanding of my error.

<?php

// rrdtool info /var/www/snmp.rrd Debugging command

while (1) {
  sleep (1);
  $file = "snmp";
  $rrdFile = dirname(__FILE__) . "/".$file.".rrd";
  $in = "ifInOctets";
  $out = "ifOutOctets";
  $count = "sysUpTime";

  $options = array(
       "--start","now -10s", // Now -10 seconds (default)
       "--step", "10", // Step size of 300 seconds 5 minutes
       "DS:".$in.":COUNTER:20:U:U",
       "DS:".$out.":COUNTER:20:U:U",
       "DS:".$count.":COUNTER:20:U:U",
       /* DS:ds-name:DST:dst arguments
          (DST: GAUGE, COUNTER, DERIVE, and ABSOLUTE):heartbeat:min:max
          heartbeat: in case that there is not input up to 600 seconds
          then the input will characterised as undefined (blank)
          Based on Nyquist rate (Fs >= 2 * Fmax) 300 (step) 600 (heartbeat)
          32-bit = 2^32-1 = 4294967295 (counter ticks)
          64-bit = 2^64-1 = 18446744073709551615 (counter ticks)
          64-bit counter (caution!!!) different oid's
       */
       "RRA:MIN:0.5:10:300",
       "RRA:MIN:0.5:20:600",
       "RRA:MAX:0.5:10:300",
       "RRA:MAX:0.5:20:600",
       "RRA:AVERAGE:0.5:10:300",
       "RRA:AVERAGE:0.5:20:600",
       /* RRA:AVERAGE | MIN | MAX | LAST:xff:steps:rows
          xff range: 0-1 (exclusive) defines the allowed number of unknown
          *UNKNOWN* PDPs to the number of PDPs in the interval. Step defines
          how many of those data points are used to build consolidated data.
          rows defines how many data values are kept in an RRA.
       */
       );

  //create rrd file
  $create = rrd_create(
           "".$rrdFile."",
           $options
           );

  if ($create === FALSE) {
    echo "Creation error: ".rrd_error()."\n";
  }

  $ifInOctets = rand(0, 1500); // ifInOctets (OID: 1.3.6.1.2.1.2.2.1.10)
  $ifOutOctets = rand(0, 2500); // ifOutOctets (OID: 1.3.6.1.2.1.2.2.1.16)
  $sysUpTime = rand(0, 2000); // sysUpTime (OID: 1.3.6.1.2.1.1.3)

  $t = time();

  //update rrd file
  $update = rrd_update(
           "".$rrdFile."",
           array(
             /* Update database with 3 values 
            based on time now (N:timestamp) */
             "".$t.":".$ifInOctets.":".$ifOutOctets.":".$sysUpTime.""
             )
           );

  if ($update === FALSE) {
    echo "Update error: ".rrd_error()."\n";
  }

  $start = "now";
  $title = "Hourly Server Data";

  $final = array(
     "--start","".$start." -10s",
     "--step","10",
     "--title=".$title."",
     "--vertical-label=Bytes/sec",
     "--lower-limit=0",
     //"--no-gridfit",
     "--slope-mode",
     //"--imgformat","EPS",
     "DEF:".$in."_def=".$file.".rrd:".$in.":AVERAGE",
     "DEF:".$out."_def=".$file.".rrd:".$out.":AVERAGE",
     "DEF:".$count."_def=".$file.".rrd:".$count.":AVERAGE",
     "CDEF:inbits=".$in."_def,8,*",
     "CDEF:outbits=".$out."_def,8,*",
     "CDEF:counter=".$count."_def,8,*",
     /* "VDEF:".$in_min."=inbits,MINIMUM",
        "VDEF:".$out_min."=outbits,MINIMUM",
        "VDEF:".$in_max."=inbits,MAXIMUM",
        "VDEF:".$out_max."=outbits,MAXIMUM",
        "VDEF:".$in_av."=inbits,AVERAGE",
        "VDEF:".$out_av."=outbits,AVERAGE", */
     "COMMENT:\\n",
     "LINE:".$in."_def#FF00FF:".$in."",
     "GPRINT:inbits:LAST:last \: %6.2lf %SBps",
     "COMMENT:\\n",
     "LINE:".$out."_def#0000FF:".$out."",
     "GPRINT:outbits:LAST:last \: %6.2lf %SBps",
     "COMMENT:\\n",
     "LINE:".$count."_def#FFFF00:".$count."",
     "GPRINT:counter:LAST:last\: %6.2lf %SBps",
     "COMMENT:\\n",
     );

  // graph output 
  $outputPngFile = rrd_graph(
             "".$file.".png",
             $final
             );

  if ($outputPngFile === FALSE) {
    echo "<b>Graph error: </b>".rrd_error()."\n";
   }

  /*  Returns the first data sample from the 
      specified RRA of the RRD file. */
   $result = rrd_first (
           $rrdFile,
           $raaindex = 0
           );

   if ($result === FALSE) {
     echo "<b>Graph result error: </b>".rrd_error()."\n";
   }

   /* Returns the UNIX timestamp of the most 
      recent update of the RRD database. */
   $last = rrd_last (
        $rrdFile
        );

   if ($last === FALSE) {
      echo "<b>Graph result error: </b>".rrd_error()."\n";
    }

    $info = rrd_info (
        "".$rrdFile.""
        );

    if ($info === FALSE) {
      echo "<b>Graph result error: </b>".rrd_error()."\n";
    }

    /*  Gets array of the UNIX timestamp and the values stored 
        for each date in the most recent update of the RRD database file. */
    $debug = rrd_lastupdate (
           "".$rrdFile.""
           );

     if ($debug === FALSE) {
       echo "<b>Graph result error: </b>".rrd_error()."\n";
     }

     var_dump ($debug);

     /* $version = rrd_version ( );
        echo "This is the version ".$version."\n"; */

} // End of while condition 
?>
thanos
  • 111
  • 1
  • 4
  • 10

1 Answers1

2

There are a lot of issues in your code.

Firstly, your RRD file is apparently re-created in every iteration of your While loop! This will overwrite the previous loop's update.

Secondly, although you create the RRD with a step size of 10, you are not doing a sleep(10) at the end of each update loop. You cannot update the RRD more frequently than the Step size.

Thirdly, you have used a COUNTER type for the DS, which assumes an constantly increasing count. However your test data are random numbers and so not increasing. A decrease may be taken as a counter wraparound, so a huge number, which is outside the valid range for your DS - and hence an Unknown is stored.

Fourthly, you need to have two consecutive updates for a Counter to have a valid rate; you are overwriting your RRD file each iteration and so never manage to get this.

Fifthly, your smallest RRA being defined has a COunt of 10; this means you need 10 data points to make a single consolidated pointin the RRA. With a Step of 10sec, this means you need to run for 110sec (11 updates) before you even have a single data point to plot. You should probably try adding a Count 1 RRA.

And finally, your graph is being requested for a 10 second time window. This is less than one RRA sample. Remember, you r Step is 10s and your smallest RRA is count=10, so a consolidated step of 100s.

I suggest you fix the loop so that the create comes outside; make the sleep equivalent to the RRD step; add a Count 1 AVG RRA; and make your graph request for a longer time window.

Steve Shipway
  • 3,754
  • 3
  • 22
  • 39
  • Thank you for the information provided and the analysis on my system. I tried some modifications but still I keep ending with the same empty graph. The modifications that I applied: `sleep (10)`,`"DS:".$in.":GAUGE:2:U:U"`,`"--step", "1"`,`"RRA:MIN:0.5:2:1"` and the graph step: `"--step","15"`. Am I on the wrong direction again? I appreciate your time and effort. – thanos Apr 08 '14 at 10:32
  • I noticed that I have not specified correctly the the sleep time and the graph time the should the other way around: `sleep (15)` and `"--step","15"` but still this dose not solves my problem. I am missing something again, that I am not able to figure it out yet. – thanos Apr 08 '14 at 13:22
  • You should have your slepp() call as the same size as your --step definition. Also, unless you move your rrd_create call outside of your while() loop and make you'll never get anything! Finally, if you want to use those random update values, you should use a GAUGE type of DS, not COUNTER. Deal with all 6 of the issues I've mentioned in my original post if you want it to work. – Steve Shipway Apr 09 '14 at 04:20
  • Thank you for your time and effort. I will work with the values to try to understand how the rrd database works and updates data. – thanos Apr 09 '14 at 23:08