<?php
/*
* weathermap5rrd - configfile.php
* Copyright (C) 2008 Zdenek Styblik
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Authors:
* Zdenek Styblik ~ 2007-2008
* Alexandre Fontelle ~ 2005-2006
*
* This script is a modified version of rrd.php
* of Cacti project (http://www.cacti.net)
*
*/
class rrdtools
{
function __construct()
{
if (!defined('RRD_NL'))
define('RRD_NL', "\\\n");
if (!defined('RRD_MAX_FETCH_CACHE_SIZE'))
define('RRD_MAX_FETCH_CACHE_SIZE', 5);
if (!defined('RRD_PATH'))
define('RRD_PATH', "/usr/bin/rrdtool");
}
# @return: string;
public function escape_command($command)
{
return preg_replace('/(\\\$|`)/', "", $command);
}
# @return: int;
public function rrd_get_fd(&$rrd_struc, $fd_type)
{
if (sizeof($rrd_struc) == 0)
{
return 0;
}
else
{
return $rrd_struc["fd"];
} /* not sizeof */
}
# @return: string;
public function rrdtool_last($filename)
{
$cmd_line="last {$filename}";
$retval = $this->rrdtool_execute($cmd_line, false, 'RRDTOOL_OUTPUT_STDOUT');
return $retval;
}
# @return: array;
public function rrdtool_get_last_value($rrdfile, $pos = 0, $rrdstep = 600)
{
$start = $this->rrdtool_last($rrdfile);
$unixtime = $start;
if ($this->rrdtool_getversion() == "1.2")
{
$end = $start;
$start = $start - $rrdstep;
}
else
{
$end=$start;
} /* not $this->rrdtool_getversion() */
$result = $this->rrdtool_function_fetch($rrdfile, $start, $end);
# Get values from array read before and convert values in bytes
return $result["values"][$pos-1][0];
}
# @return: string;
public function rrdtool_execute($command_line, $log_to_stdout,
$output_flag = 'RRDTOOL_OUTPUT_STDOUT', $rrd_struc = array(), $logopt = "WEBLOG")
{
/* WIN32: before sending this command off to rrdtool, get rid
* of all of the '\' characters. Unix does not care; win32 does.
* Also make sure to replace all of the fancy \'s at the end of the line,
* but make sure not to get rid of the "\n"'s that are supposed to be
* in there (text format)
*/
$command_line = str_replace("\\\n", " ", $command_line);
/* output information to the log file if appropriate
* if (read_config_option("log_verbosity") >= POLLER_VERBOSITY_DEBUG) {
* cacti_log("CACTI2RRD: " . read_config_option("path_rrdtool") . " $command_line",
* $log_to_stdout, $logopt);
* }
*/
/* if we want to see the error output from rrdtool; make sure to specify this */
if (($output_flag == 'RRDTOOL_OUTPUT_STDERR') && (sizeof($rrd_struc) == 0))
{
$command_line .= " 2>&1";
}
/* use popen to eliminate the zombie issue */
/* an empty $rrd_struc array means no fp is available */
# echo "rrdtool=$this->rrdtool<br>";
if (sizeof($rrd_struc) == 0)
{
$rrdtool = RRD_PATH;
$fp = popen("{$rrdtool}". $this->escape_command(" {$command_line}"), "r");
}
else
{
fwrite($this->rrd_get_fd($rrd_struc, 'RRDTOOL_PIPE_CHILD_READ'),
$this->escape_command(" {$command_line}") . "\r\n");
fflush($this->rrd_get_fd($rrd_struc, 'RRDTOOL_PIPE_CHILD_READ'));
} /* not sizeof */
switch ($output_flag)
{
case 'RRDTOOL_OUTPUT_NULL':
return; break;
case 'RRDTOOL_OUTPUT_STDERR':
if (isset($fp))
{
$output = fgets($fp, 1000000);
if (substr($output, 1, 3) == "PNG")
{
return "OK";
}
if (substr($output, 0, 5) == "GIF87")
{
return "OK";
}
print $output;
} /* isset($fp) */
break;
case 'RRDTOOL_OUTPUT_GRAPH_DATA':
if (isset($fp))
{
return fpassthru($fp);
}
break;
default:
if (isset($fp))
{
$line = "";
while (!feof($fp)) {
$line .= fgets($fp, 4096);
}
return $line;
}
break;
} /* switch */
}
# desc: rrdtool_function_fetch - given a data source, return all of its data in an array
# $local_data_id: the data source to fetch data for;
# $start_time: the start time to use for the data calculation. this value can
# either be absolute (unix timestamp) or relative (to now)
# $end_time: the end time to use for the data calculation. this value can
# either be absolute (unix timestamp) or relative (to now)
# $resolution: the accuracy of the data measured in seconds
# @return: array; an array containing all data in this data source broken down
# by each data source item.
# NULL when failed;
public function rrdtool_function_fetch($local_data_id, $start_time, $end_time, $resolution = 0)
{
if (empty($local_data_id) || !file_exists($local_data_id) || !is_readable($local_data_id))
{
$retval = NULL;
}
else
{
$regexps = array();
$fetch_array = array();
#$data_source_path = get_data_source_path($local_data_id, true);
$data_source_path = $local_data_id;
/* build and run the rrdtool fetch command with all of our data */
$cmd_line = "fetch $data_source_path AVERAGE -s $start_time -e $end_time";
if ($resolution > 0)
{
$cmd_line .= " -r $resolution";
}
$output = $this->rrdtool_execute($cmd_line, false, 'RRDTOOL_OUTPUT_STDOUT');
/* grab the first line of the output which contains a list of data sources
* in this .rrd file
*/
$line_one = substr($output, 0, strpos($output, "\n"));
/* loop through each data source in this .rrd file ... */
if (preg_match_all("/\s+/", $line_one, $data_source_names))
{
/* version 1.0.49 changed the output slightly */
if (preg_match("/^timestamp/", $line_one))
{
array_shift($data_source_names[0]);
}
$fetch_array["data_source_names"] = $data_source_names[0];
/* build a unique regexp to match each data source individually when
* passed to preg_match_all()
*/
for ($i = 0; $i < count($fetch_array["data_source_names"]); $i++)
{
$regexps[$i] = '/[0-9]+:\s+';
for ($j = 0; $j < count($fetch_array["data_source_names"]); $j++)
{
/* it seems that at least some versions of the Windows RRDTool binary pads
* the exponent to 3 digits, rather than 2 on every Unix version that I have
* ever seen
*/
if ($j == $i)
{
$regexps[$i].= '([\-]?[0-9]{1}\.[0-9]+)e([\+-][0-9]{2,3})';
}
else
{
$regexps[$i].= '[\-]?[0-9]{1}\.[0-9]+e[\+-][0-9]{2,3}';
} /* not $j == $i */
if ($j < count($fetch_array["data_source_names"]))
{
$regexps[$i].= '\s+';
}
} /* for j = 0 */
$regexps[$i].= '/';
} /* for i = 0 */
} /* preg_match */
/* loop through each regexp determined above (or each data source) */
for ($i = 0; $i < count($regexps); $i++)
{
$fetch_array["values"][$i] = array();
/* match the regexp against the rrdtool fetch output to get a mantisa and
* exponent for each line
*/
if (preg_match_all($regexps[$i], $output, $matches))
{
for ($j = 0; $j < count($matches[1]); $j++)
{
$line = ($matches[1][$j] * (pow(10,(float)$matches[2][$j])));
array_push($fetch_array["values"][$i], ($line * 1));
} /* for $j = 0 */
} /* preg_match */
} /* for $i = 0 */
# echo LIST_CONTENTS($fetch_array);
$retval = $fetch_array;
} /* (empty($local_file... */
return $retval;
}
# @return: array/NULL;
public function get_rra_name($rrdfile, $rrapos)
{
if (empty($rrdfile) || !file_exists($rrdfile) || !is_readable($rrdfile))
{
$retval = NULL;
}
else
{
# [Thu Sep 25 23:41:52 2008] [error] [client 127.0.0.1] PHP Notice: Undefined offset:
# 0 in /home/stybla/work/weathermap/weathermap5rrd-1.3.11/lib/rrd.php on line 263
$fetch_array = array();
$data_source_path = $rrdfile;
/* build and run the rrdtool fetch command with all of our data */
$cmd_line = "fetch {$data_source_path} AVERAGE --start=now";
# if ($resolution > 0) {
# $cmd_line .= " -r $resolution";
# }
$output = $this->rrdtool_execute($cmd_line, false, 'RRDTOOL_OUTPUT_STDOUT');
/* grab the first line of the output which contains a list of data sources
in this .rrd file */
$line_one = substr($output, 0, strpos($output, "\n"));
#echo "line_one=*$line_one*<br>";
/* loop through each data source in this .rrd file ... */
#if (preg_match_all("/\S+/", $line_one, $data_source_names)) {
preg_match_all("/\S+/", $line_one, $data_source_names);
#echo "datasourcenames=".$data_source_names[0][0]."<br>";
#echo LIST_CONTENTS($data_source_names);
$retval = $data_source_names[0][$rrapos-1];
} /* not empty */
return $retval;
}
# @return: image;
public function rrdtool_graph($rrdfilein, $rranamein, $rrdfileout, $rranameout,
$nodea, $nodeb, $period, $coefin, $coefout)
{
$timenow = time();
$datenow = date("d/m/Y ").date("H")."\:".date("i")."\:".date("s");
if (!$period)
$period="6hours";
$cmd_line = "graph - ".
'--imgformat=PNG ' .
'--start=now-'. $period .
' --end=now ' .
'--title="'. $nodea. ' - '. $nodeb. '" ' .
'--rigid ' .
'--base=1024 ' .
'--height=120 ' .
'--width=500 ' .
'--alt-autoscale-max ' .
'--lower-limit=0 ' .
'COMMENT:" " ' .
'COMMENT:" \n" ' .
'--vertical-label="Bits per second" ' .
'DEF:a="' . $rrdfilein .
'":' . $rranamein . ':AVERAGE ' .
'DEF:b="' . $rrdfileout .
'":' . $rranameout . ':AVERAGE ' .
'CDEF:cdefa=a,' . $coefin . ',* ' .
'CDEF:cdefa2=cdefa,8,* ' .
'CDEF:cdefb=b,' . $coefout . ',* ' .
'CDEF:cdefb2=cdefb,8,* ' .
'AREA:cdefa2#00CF00:"' . $nodeb . '-->' . $nodea . '" ' .
'GPRINT:cdefa2:LAST:" Cur\:%8.2lf %s" ' .
'GPRINT:cdefa2:AVERAGE:"A/ver\:%8.2lf %s" ' .
'GPRINT:cdefa2:MAX:"Max\:%8.2lf %s\n" ' .
'LINE1:cdefb2#002A97:"' . $nodea . '-->' . $nodeb . '" ' .
'GPRINT:cdefb2:LAST:"Cur\:%8.2lf %s" ' .
'GPRINT:cdefb2:AVERAGE:"Aver\:%8.2lf %s" ' .
'GPRINT:cdefb2:MAX:"Max\:%8.2lf %s\n" ' .
'COMMENT:" \n" ' .
'COMMENT:"\t\t\t\t\t\t\t\tTime period\: ' . $period . ' \n" ' .
'COMMENT:"\t\t\t\t\t\t\t\tGraph generated\: ' . $datenow . ' \n" ';
header("Content-type: image/png");
$rrdtool = RRD_PATH;
$fp = popen("{$rrdtool} {$cmd_line}","r");
$retval = fpassthru($fp);
pclose($fp);
return $retval;
}
# @return: string;
public function rrdtool_getversion()
{
$rrdtool = RRD_PATH;
$handle = popen($rrdtool .'|grep "hide@address.com" | cut -d" " -f2 2>&1', 'r');
$read = fread($handle, 2096);
list($major, $majorsub, $minorsub)= explode(".", $read);
pclose($handle);
return ($major.".".$majorsub);
}
# desc: return link coeficient based uppon link units;
# $unit: string;
# @return: float;
public function rrdtool_getLinkCoef($unit = null)
{
switch ($unit)
{
case "Gbits":
$retval = 10000*10000/8;
break;
case "Mbits":
$retval = 1000*1000/8;
break;
case "Kbits":
$retval = 1000/8;
break;
case "bits":
$retval = 1/8;
break;
case "Mbytes":
$retval = 1024*1024;
break;
case "Kbytes":
$retval = 1024;
break;
case "bytes":
$retval = 1;
break;
default:
// Kbits
$retval = 1000/8;
break;
} /* switch */
return $retval;
}
}
?>