Search code examples
phpgraphfloating-pointrrdtoolrrd

php RRD Graph floating values instead of integers


enter image description hereI am producing an rrd graph and I am facing 2 problems.

Problem 1: The numbers that I am printing they are integers without decimals, although when they are printed decimals appear. It is really confusing. So I looked online on the rrdgraph_graph and although that I am using the correct syntax and I am not applying any calculations I still do get floating values instead of integers.

According to the official website: %s place this after %le, %lf or %lg. This will be replaced by the appropriate SI magnitude unit and the value will be scaled accordingly (123456 -> 123.456 k).

I have attached a photo as sample of the output. I have also provide a working example code so if anyone understands the RRD's can view possible the error.

Problem 2: I was trying to add on my graph the VRULE:time#color[:legend][:dashes[=on_s[,off_s[,on_s,off_s]...]][:dash-offset=offset]] function and based on the online instructions I can supply the time. Since my graph is shifting I was planning to do time (value) - 1800 sec. I wanted to place a vertical line in the middle of the graph so I could view approximately an average on 30 minutes values. When I am applying such a format I get this error:

<b>Graph error: </b>parameter '1400274668-1800' does not represent time in line VRULE:1400274668-1800#0000CD:Half way values

When I remove the subtraction everything work fine. Is there a way to produce this line in the middle of my graph?

<?php

$file = "snmp";
$rrdFile = dirname(__FILE__) . "/".$file.".rrd";
$in = "losses";
$png = "/home/linux/Desktop/";
$in_min = "vdef_in_min";
$in_max = "vdef_in_max";
$in_lst = "vdef_in_lst";
$in_av = "vdef_in_av";
$title = "Losses RRD::Graph";
$output = array("1h","1d");
$step = 5;
$heartbeat = 2 * $step;

while (1) { 
  sleep (1);

  $options = array(
           "--start","now -15s",
           "--step", "".$step."",
           "DS:".$in.":GAUGE:".$heartbeat.":0:U",
           "RRA:LAST:0.5:1:3600",
           "RRA:MIN:0.5:1:3600",
           "RRA:MAX:0.5:1:3600",
           "RRA:AVERAGE:0.5:6:600",
           "RRA:LAST:0.5:300:288",
           "RRA:MIN:0.5:300:288",
           "RRA:MAX:0.5:300:288`",
           "RRA:AVERAGE:0.5:600:144"
           );

   if ( !isset( $create ) ) {

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

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

  $t = time();
  $losses = rand(0, 150);

  $update = rrd_update(
               "".$rrdFile."",
               array(
                 "".$t.":".$losses.""
                 )
               );

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

  date_default_timezone_set('Europe/Stockholm');
  $timezone = new DateTime(NULL, new DateTimeZone('Europe/Stockholm'));
  $date = date('l jS \of F Y h\\:i\\:s A' , $timezone->format('U'));
  $comment = "RRD last updated:".$date;
  $comment = str_replace( ":", "\\:", $comment );
  $graph = "Graph last updated:".$date;
  $graph = str_replace( ":", "\\:", $graph );

  foreach ($output as $test) {

     $final = array(
            "--start","end - ".$test."",
            "--end", "".$t."",
            "--title=".$file." RRD::Graph with - ".$test." Periods",
            "--vertical-label=Bytes(s)/sec",
            "--right-axis-label=latency(ms)",
            "--alt-y-grid", "--rigid",
            "--width", "800", "--height", "500",
            "--lower-limit=0",
            "--no-gridfit",
            "--slope-mode",
            "DEF:".$in."_def=".$file.".rrd:".$in.":LAST",
            "CDEF:inbytes=".$in."_def",
            "VDEF:".$in_lst."=inbytes,LAST",
            "VDEF:".$in_min."=inbytes,MINIMUM",
            "VDEF:".$in_max."=inbytes,MAXIMUM",
            "VDEF:".$in_av."=inbytes,AVERAGE",
            "COMMENT:\\n",
            "LINE2:".$in."_def#FF0000:".$in."",
            "GPRINT:".$in_min.": Minimum\:%6.2lf %S",
            "GPRINT:".$in_max.":Maximum\:%6.2lf %S",
            "GPRINT:".$in_lst.":Last\:%6.2lf %s",
            "GPRINT:".$in_av.":Average\:%6.2lf %s",
            "COMMENT:\\n",
            "VRULE:".$t."#0000CD:Half way values",
            "COMMENT:\\n",
            "HRULE:50#FFFF00:Maximum value",
            "COMMENT:\\n",
            "COMMENT: ",
            "COMMENT:\\n",
            "COMMENT:".$comment."\\r",
            "COMMENT:".$graph."\\r"
            );

    $outputPngFile = rrd_graph(
                   "".$png."".$test.".png",
                   $final
                   );

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

   }

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

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

   var_dump ($debug);
 }

?>

Solution

  • The answer to your first problem is almost certainly Data Normalisation. Since you are not updating the RRD precisely on the Step boundary every time, the submitted data values are normalised to a step boundary, resulting in the decimal values. To understand this, read Alex van den Bogeardt's excellent article on the subject.

    Your second problem is that you simply cannot use the VRULE declaration in that way. The first parameter to VRULE may be either a number or a VDEF variable, but it cannot be a formula. Therefore, VRULE:12345678#0000CD:Foo is fine, as is VRULE:vdefname#FF00FF:Bar. However you may not use VRULE:123456-123#0000CD:No. Do the calculation before, like this:

    "VRULE:".($t-1800)."#0000CD:Half way values",
    

    ... and this should result in a valid syntax.