Date created: Tuesday, December 31, 2013 9:56:19 AM. Last modified: Saturday, April 1, 2017 8:32:11 AM
95th Percentile Calculation
The following PHP script calculates the 95th percentile from a typical RRD file using two DS' (in this example, 'traffic_in' and 'traffic_out') and then generates a graph using rrdtools and parses the 95th percentile value to the graph as a COMMENT and HRULE. It's a classic ISP joint in & out 95th calculation;
<?php $rrd="/var/lib/cacti/rra/router1_traffic_in_2078.rrd"; $start="1383264000"; $end="1385855700"; $rrdtmpfile="/tmp/rrd_values"; // Blank out a file and dump this months values from rrd file exec("echo \"\" > $rrdtmpfile"); exec("rrdtool fetch -s $start -e $end $rrd MAX > $rrdtmpfile"); exec("sed -i 1,+1d $rrdtmpfile"); // remove the titles from the rrd output // Blank out a new file for sorting into max values exec("echo \"\" > $rrdtmpfile"."_max"); // Open file for writing and sort it $handle_in = fopen("$rrdtmpfile", "r"); $handle_out = fopen("$rrdtmpfile"."_max", "w"); $lastin = 0.0; $innow = 0; $lastout = 0.0; $outnow = 0; $average = 0; $samples = 0; while(!feof($handle_in)) { $line = fgets($handle_in); $values = explode(" ", $line); if($values[1]=="nan") { $innow = $lastin; } else { $innow = sprintf("%f", $values[1]); $lastin = $innow; } if($values[2]=="nan") { $outnow = $lastout; } else { $outnow = sprintf("%f", $values[2]); $lastout = $outnow; } if($innow >= $outnow) { fwrite($handle_out, $innow."\n"); $average=$average+$innow; } else { fwrite($handle_out, $outnow."\n"); $average=$average+$outnow; } $samples=$samples+1; } fclose($handle_in); fclose($handle_out); //Calculate an average $average=$average/$samples; // Now we have filled ./rrd_values_max with the MAX value from each time period, // sort them in desending order exec("sort -g -r $rrdtmpfile"."_max > $rrdtmpfile"."_max_sorted"); // Remove any blank lines (typically one on the end) exec("sed '/^$/d' $rrdtmpfile"."_max_sorted > $rrdtmpfile"."_max_sorted_trim"); // Get the highest/max value from the first line of the file $max = shell_exec("head -n 1 $rrdtmpfile"."_max_sorted_trim"); // Ge the lowest/minimum value from the last line of the file $min = shell_exec("tail -n 1 $rrdtmpfile"."_max_sorted_trim"); // Count the number of lines of rrd values $linecount = shell_exec("grep -c ^ $rrdtmpfile"."_max_sorted_trim"); // Get 5 percent of the line count value, round it down with floor() $fivepc = floor(($linecount/100)*5); // Now read the value from the line, 5% down from the top of the line count of the file $ninetyfifth = shell_exec("awk -v n1=$fivepc 'NR==n1' $rrdtmpfile"."_max_sorted_trim"); $ninetyfifth = trim($ninetyfifth); // Round it up //$ninetyfifth = ceil($ninetyfifth); // Convert to bps,kbps,mbps $ninetyfifthbps = ceil(($ninetyfifth*8)); $ninetyfifthkbps = round(($ninetyfifthbps/1000), 2); $ninetyfifthmbps = ($ninetyfifthbps/1000)/1000; $rrdcmd = "/usr/bin/rrdtool graph /tmp/php-graph.png ". "--imgformat=PNG ". "--start=$start ". "--end=$end ". "--rigid ". "--base=1000 ". "--height=120 ". "--width=500 ". "--alt-autoscale-max ". "--lower-limit=0 ". "COMMENT:\"From ".date("Y-m-d H", $start)."\:".date(i, $start)."\:".date(s, $start). " to ".date("Y-m-d H", $end)."\:".date(i, $end)."\:".date(s, $end)."\c\" ". "COMMENT:\" \c\" ". "--vertical-label='bits per second' ". "--slope-mode ". "--font TITLE:10: ". "--font AXIS:8: ". "--font LEGEND:7: ". "--font UNIT:8: ". "DEF:in=\"$rrd\":traffic_in:MAX ". "DEF:out=\"$rrd\":traffic_out:MAX ". "VDEF:inbytesavg=in,AVERAGE ". "VDEF:outbytesavg=out,AVERAGE ". "CDEF:inbytesmod=in,UN,inbytesavg,in,IF ". "CDEF:outbytesmod=out,UN,outbytesavg,out,IF ". "CDEF:speedin=in,8,* ". "CDEF:speedout=out,8,* ". "VDEF:intotal=inbytesmod,TOTAL ". "VDEF:outtotal=outbytesmod,TOTAL ". "AREA:speedin#00CF00FF:\"Inbound\" ". "GPRINT:speedin:LAST:\"Current\:%8.2lf %s\" ". "GPRINT:speedin:AVERAGE:\"Average\:%8.2lf %s\" ". "GPRINT:speedin:MAX:\"Maximum\:%8.2lf %s\" ". "GPRINT:intotal:\"Total In\:%8.2lf %s\" ". "COMMENT:\" \c\" ". "LINE1:speedout#002A97FF:\"Outbound\" ". "GPRINT:speedout:LAST:\"Current\:%8.2lf %s\" ". "GPRINT:speedout:AVERAGE:\"Average\:%8.2lf %s\" ". "GPRINT:speedout:MAX:\"Maximum\:%8.2lf %s\" ". "GPRINT:outtotal:\"Total Out\:%8.2lf %s \c\" ". "COMMENT:\" \c\" ". "HRULE:$ninetyfifthbps#FF0000FF:\"95th Percentile\" ". "COMMENT:\"($ninetyfifthmbps mbit in+out)\c\" ". "PRINT:intotal:\"%8.2lf%SBs In\" ". "PRINT:outtotal:\"%8.2lf%SBs Out\" ". "PRINT:speedin:AVERAGE:\"%8.2lf%sbps In\" ". "PRINT:speedout:AVERAGE:\"%8.2lf%sbps Out\" ". "PRINT:speedin:MAX:\"%8.2lf%sbps In\" ". "PRINT:speedout:MAX:\"%8.2lf%sbps Out\" "; exec ($rrdcmd, $cmdout); // Clean up - Commment out to see each stage of the calculation //exec("rm $rrdtmpfile"); //exec("rm $rrdtmpfile"."_max"); //exec("rm $rrdtmpfile"."_max_sorted"); //exec("rm $rrdtmpfile"."_max_sorted_trim"); ?>
Previous page: 95th Percentile Accuracy with RRDTools
Next page: Cacti Graphing Precision