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