weathermap |
Subversion Repositories: |
Rev 1 | Rev 85 | |
---|---|---|
Line 2... | Line 2... | |
// RRDtool datasource plugin. |
// RRDtool datasource plugin. | |
// gauge:filename.rrd:ds_in:ds_out |
// gauge:filename.rrd:ds_in:ds_out | |
// filename.rrd:ds_in:ds_out |
// filename.rrd:ds_in:ds_out | |
// filename.rrd:ds_in:ds_out |
// filename.rrd:ds_in:ds_out | |
// |
// | |
| ||
include_once(dirname(__FILE__)."/../ds-common.php"); | ||
| ||
class WeatherMapDataSource_rrd extends WeatherMapDataSource { |
class WeatherMapDataSource_rrd extends WeatherMapDataSource { | |
|
| |
function Init(&$map) |
function Init(&$map) | |
{ |
{ | |
if (file_exists($map->rrdtool)) { |
global $config; | |
if((function_exists('is_executable')) && (!is_executable($map->rrdtool))) |
#if (extension_loaded('RRDTool')) // fetch the values via the RRDtool Extension | |
#{ | ||
# debug("RRD DS: Using RRDTool php extension.\n"); | ||
# return(TRUE); | ||
# } | ||
# else | ||
# { | ||
if($map->context=='cacti') | ||
{ | ||
debug("RRD DS: path_rra is ".$config["rra_path"]." - your rrd pathname must be exactly this to use poller_output\n"); | ||
// save away a couple of useful global SET variables | ||
$map->add_hint("cacti_path_rra",$config["rra_path"]); | ||
$map->add_hint("cacti_url",$config['url_path']); | ||
} | ||
if (file_exists($map->rrdtool)) { | ||
if((function_exists('is_executable')) && (!is_executable($map->rrdtool))) | ||
{ | ||
warn("RRD DS: RRDTool exists but is not executable? [WMRRD01]\n"); | ||
return(FALSE); | ||
} | ||
$map->rrdtool_check="FOUND"; | ||
return(TRUE); | ||
} | ||
// normally, DS plugins shouldn't really pollute the logs | ||
// this particular one is important to most users though... | ||
if($map->context=='cli') | ||
{ |
{ | |
warn("RRD DS: RRDTool exists but is not executable?\n"); |
warn("RRD DS: Can't find RRDTOOL. Check line 29 of the 'weathermap' script.\nRRD-based TARGETs will fail. [WMRRD02]\n"); | |
return(FALSE); |
||
} |
} | |
$map->rrdtool_check="FOUND"; |
if($map->context=='cacti') | |
return(TRUE); |
{ // unlikely to ever occur | |
} |
warn("RRD DS: Can't find RRDTOOL. Check your Cacti config. [WMRRD03]\n"); | |
// normally, DS plugins shouldn't really pollute the logs |
} | |
// this particular one is important to most users though... |
# } | |
if($map->context=='cli') |
||
{ |
||
warn("RRD DS: Can't find RRDTOOL. Check line 29 of the 'weathermap' script.\nRRD-based TARGETs will fail.\n"); |
||
} |
||
if($map->context=='cacti') |
||
{ // unlikely to ever occur |
||
warn("RRD DS: Can't find RRDTOOL. Check your Cacti config.\n"); |
||
} |
||
|
| |
return(FALSE); |
return(FALSE); | |
} |
} | |
|
| |
function Recognise($targetstring) |
function Recognise($targetstring) | |
Line 45... | Line 64... | |
{ |
{ | |
return FALSE; |
return FALSE; | |
} |
} | |
} |
} | |
|
| |
// Actually read data from a data source, and return it |
function wmrrd_read_from_poller_output($rrdfile,$cf,$start,$end,$dsnames, &$data, &$map, &$data_time, &$item) | |
// returns a 3-part array (invalue, outvalue and datavalid time_t) |
||
// invalue and outvalue should be -1,-1 if there is no valid data |
||
// data_time is intended to allow more informed graphing in the future |
||
function ReadData($targetstring, &$map, &$item) |
||
{ |
{ | |
$in_ds = "traffic_in"; |
global $config; | |
$out_ds = "traffic_out"; |
| |
$rrdfile = $targetstring; |
debug("RRD ReadData: poller_output style\n"); | |
| ||
if(isset($config)) | ||
{ | ||
// take away the cacti bit, to get the appropriate path for the table | ||
// $db_rrdname = realpath($rrdfile); | ||
$path_rra = $config["rra_path"]; | ||
$db_rrdname = $rrdfile; | ||
$db_rrdname = str_replace($path_rra,"<path_rra>",$db_rrdname); | ||
debug("******************************************************************\nChecking weathermap_data\n"); | ||
foreach (array(IN,OUT) as $dir) | ||
{ | ||
debug("RRD ReadData: poller_output - looking for $dir value\n"); | ||
if($dsnames[$dir] != '-') | ||
{ | ||
debug("RRD ReadData: poller_output - DS name is ".$dsnames[$dir]."\n"); | ||
| ||
$SQL = "select * from weathermap_data where rrdfile='".mysql_real_escape_string($db_rrdname)."' and data_source_name='".mysql_real_escape_string($dsnames[$dir])."'"; | ||
| ||
$SQLcheck = "select data_template_data.local_data_id from data_template_data,data_template_rrd where data_template_data.local_data_id=data_template_rrd.local_data_id and data_template_data.data_source_path='".mysql_real_escape_string($db_rrdname)."' and data_template_rrd.data_source_name='".mysql_real_escape_string($dsnames[$dir])."'"; | ||
$SQLvalid = "select data_template_rrd.data_source_name from data_template_data,data_template_rrd where data_template_data.local_data_id=data_template_rrd.local_data_id and data_template_data.data_source_path='".mysql_real_escape_string($db_rrdname)."'"; | ||
| ||
$worst_time = time() - 8*60; | ||
$result = db_fetch_row($SQL); | ||
// OK, the straightforward query for data failed, let's work out why, and add the new data source if necessary | ||
if(!isset($result['id'])) | ||
{ | ||
debug("RRD ReadData: poller_output - Adding new weathermap_data row for $db_rrdname:".$dsnames[$dir]."\n"); | ||
$result = db_fetch_row($SQLcheck); | ||
if(!isset($result['local_data_id'])) | ||
{ | ||
$fields = array(); | ||
$results = db_fetch_assoc($SQLvalid); | ||
foreach ($results as $result) | ||
{ | ||
$fields[] = $result['data_source_name']; | ||
} | ||
if(count($fields) > 0) | ||
{ | ||
warn("RRD ReadData: poller_output: ".$dsnames[$dir]." is not a valid DS name for $db_rrdname - valid names are: ".join(", ",$fields)." [WMRRD07]\n"); | ||
} | ||
else | ||
{ | ||
warn("RRD ReadData: poller_output: $db_rrdname is not a valid RRD filename within this Cacti install. <path_rra> is $path_rra [WMRRD08]\n"); | ||
} | ||
} | ||
else | ||
{ | ||
// add the new data source (which we just checked exists) to the table. | ||
// Include the local_data_id as well, to make life easier in poller_output | ||
// (and to allow the cacti: DS plugin to use the same table, too) | ||
$SQLins = "insert into weathermap_data (rrdfile, data_source_name, sequence, local_data_id) values ('".mysql_real_escape_string($db_rrdname)."','".mysql_real_escape_string($dsnames[$dir])."', 0,".$result['local_data_id'].")"; | ||
debug("RRD ReadData: poller_output - Adding new weathermap_data row for data source ID ".$result['local_data_id']."\n"); | ||
db_execute($SQLins); | ||
} | ||
} | ||
else | ||
{ // the data table line already exists | ||
debug("RRD ReadData: poller_output - found weathermap_data row\n"); | ||
// if the result is valid, then use it | ||
if( ($result['sequence'] > 2) && ( $result['last_time'] > $worst_time) ) | ||
{ | ||
$data[$dir] = $result['last_calc']; | ||
$data_time = $result['last_time']; | ||
debug("RRD ReadData: poller_output - data looks valid\n"); | ||
} | ||
else | ||
{ | ||
$data[$dir] = 0; | ||
debug("RRD ReadData: poller_output - data is either too old, or too new\n"); | ||
} | ||
// now, we can use the local_data_id to get some other useful info | ||
// first, see if the weathermap_data entry *has* a local_data_id. If not, we need to update this entry. | ||
$ldi = 0; | ||
if(!isset($result['local_data_id']) || $result['local_data_id']==0) | ||
{ | ||
$r2 = db_fetch_row($SQLcheck); | ||
if(isset($r2['local_data_id'])) | ||
{ | ||
$ldi = $r2['local_data_id']; | ||
debug("RRD ReadData: updated local_data_id for wmdata.id=" . $result['id'] . "to $ldi\n"); | ||
// put that in now, so that we can skip this step next time | ||
db_execute("update weathermap_data set local_data_id=".$r2['local_data_id']." where id=".$result['id']); | ||
| ||
} | ||
} | ||
else | ||
{ | ||
$ldi = $result['local_data_id']; | ||
} | ||
| ||
if($ldi>0) UpdateCactiData($item, $ldi); | ||
} | ||
} | ||
else | ||
{ | ||
debug("RRD ReadData: poller_output - DS name is '-'\n"); | ||
} | ||
} | ||
} | ||
else | ||
{ | ||
warn("RRD ReadData: poller_output - Cacti environment is not right [WMRRD12]\n"); | ||
} | ||
|
| |
$multiplier = 8; |
debug("RRD ReadData: poller_output - result is ".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[OUT])."\n"); | |
debug("RRD ReadData: poller_output - ended\n"); | ||
} | ||
| ||
function wmrrd_read_from_php_rrd($rrdfile,$cf,$start,$end,$dsnames, &$data ,&$map, &$data_time,&$item) | ||
{ | ||
// not yet implemented - use php-rrdtool to read rrd data. Should be quicker | ||
if ((1==0) && extension_loaded('RRDTool')) // fetch the values via the RRDtool Extension | ||
{ | ||
// for the php-rrdtool module, we use an array instead... | ||
$rrdparams = array("AVERAGE","--start",$start,"--end",$end); | ||
$rrdreturn = rrd_fetch ($rrdfile,$rrdparams,count($rrdparams)); | ||
print_r($rrdreturn); | ||
// XXX - figure out what to do with the results here | ||
$now = $rrdreturn['start']; | ||
$n=0; | ||
do { | ||
$now += $rrdreturn['step']; | ||
print "$now - "; | ||
for($i=0;$i<$rrdreturn['ds_cnt'];$i++) | ||
{ | ||
print $rrdreturn['ds_namv'][$i] . ' = '.$rrdreturn['data'][$n++]." "; | ||
} | ||
print "\n"; | ||
} while($now <= $rrdreturn['end']); | ||
} | ||
} | ||
| ||
# rrdtool graph /dev/null -f "" -s now-30d -e now DEF:in=../rra/atm-sl_traffic_in_5498.rrd:traffic_in:AVERAGE DEF:out=../rra/atm-sl_traffic_in_5498.rrd:traffic_out:AVERAGE VDEF:avg_in=in,AVERAGE VDEF:avg_out=out,AVERAGE PRINT:avg_in:%lf PRINT:avg_out:%lf | ||
|
| |
$inbw=-1; |
function wmrrd_read_from_real_rrdtool_aggregate($rrdfile,$cf,$aggregatefn,$start,$end,$dsnames, &$data, &$map, &$data_time,&$item) | |
$outbw=-1; |
{ | |
$data_time = 0; |
| |
debug("RRD ReadData: VDEF style, for ".$item->my_type()." ".$item->name."\n"); | ||
|
| |
if(preg_match("/^(.*\.rrd):([\-a-zA-Z0-9_]+):([\-a-zA-Z0-9_]+)$/",$targetstring,$matches)) |
$extra_options = $map->get_hint("rrd_options"); | |
| ||
// Assemble an array of command args. | ||
// In a real programming language, we'd be able to pass this directly to exec() | ||
// However, this will at least allow us to put quotes around args that need them | ||
$args = array(); | ||
$args[] = "graph"; | ||
$args[] = "/dev/null"; | ||
$args[] = "-f"; | ||
$args[] = "''"; | ||
$args[] = "--start"; | ||
$args[] = $start; | ||
$args[] = "--end"; | ||
$args[] = $end; | ||
| ||
# assemble an appropriate RRDtool command line, skipping any '-' DS names. | ||
# $command = $map->rrdtool . " graph /dev/null -f '' --start $start --end $end "; | ||
| ||
if($dsnames[IN] != '-') | ||
{ |
{ | |
$in_ds = $matches[2]; |
# $command .= "DEF:in=$rrdfile:".$dsnames[IN].":$cf "; | |
$out_ds = $matches[3]; |
# $command .= "VDEF:agg_in=in,$aggregatefn "; | |
$rrdfile = $matches[1]; |
# $command .= "PRINT:agg_in:'IN %lf' "; | |
debug("Special DS names seen ($in_ds and $out_ds).\n"); |
| |
$args[] = "DEF:in=$rrdfile:".$dsnames[IN].":$cf"; | ||
$args[] = "VDEF:agg_in=in,$aggregatefn"; | ||
$args[] = "PRINT:agg_in:'IN %lf'"; | ||
} |
} | |
|
| |
if(preg_match("/^rrd:(.*)/",$rrdfile,$matches)) |
if($dsnames[OUT] != '-') | |
{ |
{ | |
$rrdfile = $matches[1]; |
# $command .= "DEF:out=$rrdfile:".$dsnames[OUT].":$cf "; | |
# $command .= "VDEF:agg_out=out,$aggregatefn "; | ||
# $command .= "PRINT:agg_out:'OUT %lf' "; | ||
| ||
$args[] = "DEF:out=$rrdfile:".$dsnames[OUT].":$cf"; | ||
$args[] = "VDEF:agg_out=out,$aggregatefn"; | ||
$args[] = "PRINT:agg_out:'OUT %lf'"; | ||
} |
} | |
| ||
$command = $map->rrdtool; | ||
foreach ($args as $arg) | ||
{ | ||
if(strchr($arg," ") != FALSE) | ||
{ | ||
$command .= ' "' . $arg . '"'; | ||
} | ||
else | ||
{ | ||
$command .= ' ' . $arg; | ||
} | ||
} | ||
$command .= " " . $extra_options; | ||
| ||
debug("RRD ReadData: Running: $command\n"); | ||
$pipe=popen($command, "r"); | ||
| ||
$lines=array (); | ||
$count = 0; | ||
$linecount = 0; | ||
|
| |
if(preg_match("/^gauge:(.*)/",$rrdfile,$matches)) |
if (isset($pipe)) | |
{ |
{ | |
$rrdfile = $matches[1]; |
fgets($pipe, 4096); // skip the blank line | |
$multiplier = 1; |
$buffer=''; | |
$data_ok = FALSE; | ||
| ||
while (!feof($pipe)) | ||
{ | ||
$line=fgets($pipe, 4096); | ||
debug ("> " . $line); | ||
$buffer.=$line; | ||
$lines[]=$line; | ||
$linecount++; | ||
} | ||
pclose ($pipe); | ||
if($linecount>1) | ||
{ | ||
foreach ($lines as $line) | ||
{ | ||
if(preg_match('/^\'(IN|OUT)\s(\-?\d+[\.,]?\d*e?[+-]?\d*:?)\'$/i', $line, $matches)) | ||
{ | ||
debug("MATCHED: ".$matches[1]." ".$matches[2]."\n"); | ||
if($matches[1]=='IN') $data[IN] = floatval($matches[2]); | ||
if($matches[1]=='OUT') $data[OUT] = floatval($matches[2]); | ||
$data_ok = TRUE; | ||
} | ||
} | ||
if($data_ok) | ||
{ | ||
if($data[IN] === NULL) $data[IN] = 0; | ||
if($data[OUT] === NULL) $data[OUT] = 0; | ||
} | ||
} | ||
else | ||
{ | ||
warn("Not enough output from RRDTool. [WMRRD09]\n"); | ||
} | ||
} | ||
else | ||
{ | ||
warn("RRD ReadData: failed to open pipe to RRDTool: ".$php_errormsg." [WMRRD04]\n"); | ||
} |
} | |
debug ("RRD ReadDataFromRealRRDAggregate: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[OUT]).",$data_time)\n"); | ||
|
| |
} | ||
| ||
function wmrrd_read_from_real_rrdtool($rrdfile,$cf,$start,$end,$dsnames, &$data, &$map, &$data_time,&$item) | ||
{ | ||
debug("RRD ReadData: traditional style\n"); | ||
|
| |
// we get the last 800 seconds of data - this might be 1 or 2 lines, depending on when in the |
// we get the last 800 seconds of data - this might be 1 or 2 lines, depending on when in the | |
// cacti polling cycle we get run. This ought to stop the 'some lines are grey' problem that some |
// cacti polling cycle we get run. This ought to stop the 'some lines are grey' problem that some | |
// people were seeing |
// people were seeing | |
|
| |
// $item->add_note("rrdversion","1.3"); |
// NEW PLAN - READ LINES (LIKE NOW), *THEN* CHECK IF REQUIRED DS NAMES EXIST (AND FAIL IF NOT), | |
// *THEN* GET THE LAST LINE WHERE THOSE TWO DS ARE VALID, *THEN* DO ANY PROCESSING. | ||
// - this allows for early failure, and also tolerance of empty data in other parts of an rrd (like smokeping uptime) | ||
| ||
$extra_options = $map->get_hint("rrd_options"); | ||
|
| |
if(file_exists($rrdfile)) |
$values = array(); | |
$args = array(); | ||
| ||
#### $command = '"'.$map->rrdtool . '" fetch "'.$rrdfile.'" AVERAGE --start '.$start.' --end '.$end; | ||
#$command=$map->rrdtool . " fetch $rrdfile $cf --start $start --end $end $extra_options"; | ||
$args[] = "fetch"; | ||
$args[] = $rrdfile; | ||
$args[] = $cf; | ||
$args[] = "--start"; | ||
$args[] = $start; | ||
$args[] = "--end"; | ||
$args[] = $end; | ||
| ||
$command = $map->rrdtool; | ||
foreach ($args as $arg) | ||
{ |
{ | |
if(1==1) |
if(strchr($arg," ") != FALSE) | |
{ |
{ | |
debug ("RRD ReadData: Target DS names are $in_ds and $out_ds\n"); |
$command .= ' "' . $arg . '"'; | |
} | ||
else | ||
{ | ||
$command .= ' ' . $arg; | ||
} | ||
} | ||
$command .= " " . $extra_options; | ||
| ||
| ||
debug ("RRD ReadData: Running: $command\n"); | ||
$pipe=popen($command, "r"); | ||
| ||
$lines=array (); | ||
$count = 0; | ||
$linecount = 0; | ||
|
| |
$period = intval($map->get_hint('rrd_period')); |
if (isset($pipe)) | |
if($period == 0) $period = 800; |
{ | |
$start = $map->get_hint('rrd_start'); |
$headings=fgets($pipe, 4096); | |
if($start == '') { |
// this replace fudges 1.2.x output to look like 1.0.x | |
$start = "now-$period"; |
// then we can treat them both the same. | |
$end = "now"; |
$heads=preg_split("/\s+/", preg_replace("/^\s+/","timestamp ",$headings) ); | |
} |
| |
else |
fgets($pipe, 4096); // skip the blank line | |
{ |
$buffer=''; | |
$end = "start+".$period; |
||
} |
||
|
| |
$command = '"'.$map->rrdtool . '" fetch "'.$rrdfile.'" AVERAGE --start '.$start.' --end '.$end; |
while (!feof($pipe)) | |
$command=$map->rrdtool . " fetch $rrdfile AVERAGE --start $start --end $end"; |
{ | |
|
$line=fgets($pipe, 4096); | |
debug ("RRD ReadData: Running: $command\n"); |
debug ("> " . $line); | |
$pipe=popen($command, "r"); |
$buffer.=$line; | |
$lines[]=$line; | ||
$linecount++; | ||
|
| |
$lines=array (); |
} | |
$count = 0; |
pclose ($pipe); | |
$linecount = 0; |
| |
debug("RRD ReadData: Read $linecount lines from rrdtool\n"); | ||
debug("RRD ReadData: Headings are: $headings\n"); | ||
|
| |
if (isset($pipe)) |
if( (in_array($dsnames[IN],$heads) || $dsnames[IN] == '-') && (in_array($dsnames[OUT],$heads) || $dsnames[OUT] == '-') ) | |
{ |
{ | |
$headings=fgets($pipe, 4096); |
// deal with the data, starting with the last line of output | |
fgets($pipe, 4096); // skip the blank line |
$rlines=array_reverse($lines); | |
$buffer=''; |
| |
|
foreach ($rlines as $line) | |
while (!feof($pipe)) |
{ | |
debug ("--" . $line . "\n"); | ||
$cols=preg_split("/\s+/", $line); | ||
for ($i=0, $cnt=count($cols)-1; $i < $cnt; $i++) { | ||
$h = $heads[$i]; | ||
$v = $cols[$i]; | ||
# print "|$h|,|$v|\n"; | ||
$values[$h] = trim($v); | ||
} | ||
| ||
$data_ok=FALSE; | ||
| ||
foreach (array(IN,OUT) as $dir) | ||
{ |
{ | |
$line=fgets($pipe, 4096); |
$n = $dsnames[$dir]; | |
debug ("> " . $line); |
# print "|$n|\n"; | |
$buffer.=$line; |
if(array_key_exists($n,$values)) | |
$lines[]=$line; |
{ | |
$linecount++; |
$candidate = $values[$n]; | |
} |
if(preg_match('/^\-?\d+[\.,]?\d*e?[+-]?\d*:?$/i', $candidate)) | |
pclose ($pipe); |
{ | |
$data[$dir] = $candidate; | ||
debug("$candidate is OK value for $n\n"); | ||
$data_ok = TRUE; | ||
} | ||
} | ||
} | ||
|
| |
debug("RRD ReadData: Read $linecount lines from rrdtool\n"); |
if($data_ok) | |
{ | ||
// at least one of the named DS had good data | ||
$data_time = intval($values['timestamp']); | ||
|
| |
$rlines=array_reverse($lines); |
// 'fix' a -1 value to 0, so the whole thing is valid | |
$gotline=0; |
// (this needs a proper fix!) | |
$theline=''; |
if($data[IN] === NULL) $data[IN] = 0; | |
if($data[OUT] === NULL) $data[OUT] = 0; | ||
|
| |
foreach ($rlines as $line) |
// break out of the loop here | |
{ |
break; | |
debug ("--" . $line . "\n"); |
} | |
$cols=preg_split("/\s+/", $line); |
} | |
$dataok=1; |
} | |
$ii=0; |
else | |
{ | ||
// report DS name error | ||
$names = join(",",$heads); | ||
$names = str_replace("timestamp,","",$names); | ||
warn("RRD ReadData: At least one of your DS names (".$dsnames[IN]." and ".$dsnames[OUT].") were not found, even though there was a valid data line. Maybe they are wrong? Valid DS names in this file are: $names [WMRRD06]\n"); | ||
} | ||
| ||
} | ||
else | ||
{ | ||
warn("RRD ReadData: failed to open pipe to RRDTool: ".$php_errormsg." [WMRRD04]\n"); | ||
} | ||
debug ("RRD ReadDataFromRealRRD: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[OUT]).",$data_time)\n"); | ||
} | ||
|
| |
foreach ($cols as $col) |
// Actually read data from a data source, and return it | |
{ |
// returns a 3-part array (invalue, outvalue and datavalid time_t) | |
# if( ! is_numeric($col) ) { $dataok=0; } |
// invalue and outvalue should be -1,-1 if there is no valid data | |
if (trim($col) != '' && !preg_match('/^\d+\.?\d*e?[+-]?\d*:?$/i', $col)) |
// data_time is intended to allow more informed graphing in the future | |
{ |
function ReadData($targetstring, &$map, &$item) | |
$dataok=0; |
{ | |
debug ("RRD ReadData: $ii: This isn't a number: [$col]\n"); |
global $config; | |
} |
| |
$dsnames[IN] = "traffic_in"; | ||
$dsnames[OUT] = "traffic_out"; | ||
$data[IN] = NULL; | ||
$data[OUT] = NULL; | ||
$SQL[IN] = 'select null'; | ||
$SQL[OUT] = 'select null'; | ||
$rrdfile = $targetstring; | ||
|
| |
# if($col=='nan') { $dataok=0; } |
if($map->get_hint("rrd_default_in_ds") != '') { | |
$ii++; |
$dsnames[IN] = $map->get_hint("rrd_default_in_ds"); | |
} |
debug("Default 'in' DS name changed to ".$dsnames[IN].".\n"); | |
} | ||
if($map->get_hint("rrd_default_out_ds") != '') { | ||
$dsnames[OUT] = $map->get_hint("rrd_default_out_ds"); | ||
debug("Default 'out' DS name changed to ".$dsnames[OUT].".\n"); | ||
} | ||
|
| |
if ($gotline == 0 && $dataok == 1 && trim($line) != '') |
$multiplier = 8; // default bytes-to-bits | |
{ |
||
debug ("RRD ReadData: Found a good line: $line ($headings)\n"); |
||
$theline=$line; |
||
$gotline=1; |
||
$countwas=$count; |
||
} |
||
|
| |
$count++; |
$inbw = NULL; | |
} |
$outbw = NULL; | |
} |
$data_time = 0; | |
else |
||
{ |
||
warn("RRD ReadData: failed to open pipe to RRDTool: ".$php_errormsg."\n"); |
||
} |
||
|
| |
if ($theline != '') |
if(preg_match("/^(.*\.rrd):([\-a-zA-Z0-9_]+):([\-a-zA-Z0-9_]+)$/",$targetstring,$matches)) | |
{ |
{ | |
if ($countwas > 2) { warn |
$rrdfile = $matches[1]; | |
("RRD ReadData: Data is not most recent entry ($countwas) for link: $targetstring\n"); } |
| |
$dsnames[IN] = $matches[2]; | ||
$dsnames[OUT] = $matches[3]; | ||
| ||
debug("Special DS names seen (".$dsnames[IN]." and ".$dsnames[OUT].").\n"); | ||
} | ||
|
| |
debug ("RRD ReadData: Our line is $theline\n"); |
if(preg_match("/^rrd:(.*)/",$rrdfile,$matches)) | |
$cols=preg_split("/\s+/", $theline); |
{ | |
// this replace fudges 1.2.x output to look like 1.0.x |
$rrdfile = $matches[1]; | |
// then we can treat them both the same. |
} | |
$heads=preg_split("/\s+/", preg_replace("/^\s+/","timestamp ",$headings) ); |
||
|
| |
# $values = array_combine($heads,$cols); |
if(preg_match("/^gauge:(.*)/",$rrdfile,$matches)) | |
for ($i=0, $cnt=count($cols); $i < $cnt; $i++) { $values[$heads[$i]] = $cols[$i]; } |
{ | |
$rrdfile = $matches[1]; | ||
$multiplier = 1; | ||
} | ||
|
| |
// as long as no-one actually manages to create an RRD with a DS of '-', then this will just fall through to 0 for '-' |
if(preg_match("/^scale:([+-]?\d*\.?\d*):(.*)/",$rrdfile,$matches)) | |
if( isset($values[$in_ds]) || isset($values[$out_ds]) ) |
{ | |
$rrdfile = $matches[2]; | ||
$multiplier = $matches[1]; | ||
} | ||
| ||
debug("SCALING result by $multiplier\n"); | ||
| ||
// try and make a complete path, if we've been given a clue | ||
// (if the path starts with a . or a / then assume the user knows what they are doing) | ||
if(!preg_match("/^(\/|\.)/",$rrdfile)) | ||
{ | ||
$rrdbase = $map->get_hint('rrd_default_path'); | ||
if($rrdbase != '') | ||
{ | ||
$rrdfile = $rrdbase."/".$rrdfile; | ||
} | ||
} | ||
| ||
$cfname = intval($map->get_hint('rrd_cf')); | ||
if($cfname=='') $cfname='AVERAGE'; | ||
| ||
$period = intval($map->get_hint('rrd_period')); | ||
if($period == 0) $period = 800; | ||
$start = $map->get_hint('rrd_start'); | ||
if($start == '') { | ||
$start = "now-$period"; | ||
$end = "now"; | ||
} | ||
else | ||
{ | ||
$end = "start+".$period; | ||
} | ||
| ||
$use_poller_output = intval($map->get_hint('rrd_use_poller_output')); | ||
$nowarn_po_agg = intval($map->get_hint("nowarn_rrd_poller_output_aggregation")); | ||
$aggregatefunction = $map->get_hint('rrd_aggregate_function'); | ||
| ||
if($aggregatefunction != '' && $use_poller_output==1) | ||
{ | ||
$use_poller_output=0; | ||
if($nowarn_po_agg==0) | ||
{ | ||
warn("Can't use poller_output for rrd-aggregated data - disabling rrd_use_poller_output [WMRRD10]\n"); | ||
} | ||
} | ||
| ||
if($use_poller_output == 1) | ||
{ | ||
debug("Going to try poller_output, as requested.\n"); | ||
WeatherMapDataSource_rrd::wmrrd_read_from_poller_output($rrdfile,"AVERAGE",$start,$end, $dsnames, $data,$map, $data_time,$item); | ||
} | ||
| ||
// if poller_output didn't get anything, or if it couldn't/didn't run, do it the old-fashioned way | ||
// - this will still be the case for the first couple of runs after enabling poller_output support | ||
// because there won't be valid data in the weathermap_data table yet. | ||
if( ($dsnames[IN]!='-' && $data[IN] === NULL) || ($dsnames[OUT] !='-' && $data[OUT] === NULL) ) | ||
{ | ||
if($use_poller_output == 1) | ||
{ | ||
debug("poller_output didn't get anything useful. Kicking it old skool.\n"); | ||
} | ||
if(file_exists($rrdfile)) | ||
{ | ||
debug ("RRD ReadData: Target DS names are ".$dsnames[IN]." and ".$dsnames[OUT]."\n"); | ||
| ||
$values=array(); | ||
| ||
if ((1==0) && extension_loaded('RRDTool')) // fetch the values via the RRDtool Extension | ||
{ | ||
WeatherMapDataSource_rrd::wmrrd_read_from_php_rrd($rrdfile,$cfname,$start,$end, $dsnames, $data,$map, $data_time,$item); | ||
} | ||
else | ||
{ | ||
if($aggregatefunction != '') | ||
{ |
{ | |
$inbw=0; $outbw=0; |
WeatherMapDataSource_rrd::wmrrd_read_from_real_rrdtool_aggregate($rrdfile,$cfname,$aggregatefunction, $start,$end, $dsnames, $data,$map, $data_time,$item); | |
if(isset($values[$in_ds]) ) $inbw=$values[$in_ds] * $multiplier; |
||
if(isset($values[$out_ds]) ) $outbw=$values[$out_ds] * $multiplier; |
||
$data_time = $values['timestamp']; |
||
$data_time = preg_replace("/:/","",$data_time); |
||
} |
} | |
else |
else | |
{ |
{ | |
warn("RRD ReadData: Neither of your DS names ($in_ds & $out_ds) were found, even though there was a valid data line. Maybe they are wrong?"); |
// do this the tried and trusted old-fashioned way | |
WeatherMapDataSource_rrd::wmrrd_read_from_real_rrdtool($rrdfile,$cfname,$start,$end, $dsnames, $data,$map, $data_time,$item); | ||
} |
} | |
} |
} | |
} |
} | |
} |
else | |
else |
{ | |
{ |
warn ("Target $rrdfile doesn't exist. Is it a file? [WMRRD06]\n"); | |
warn ("Target $rrdfile doesn't exist. Is it a file?\n"); |
} | |
} |
} | |
|
| |
debug ("RRD ReadData: Returning ($inbw,$outbw,$data_time)\n"); |
// if the Locale says that , is the decimal point, then rrdtool | |
|
// will honour it. However, floatval() doesn't, so let's replace | |
return( array($inbw, $outbw, $data_time) ); |
// any , with . (there are never thousands separators, luckily) | |
// | ||
if($data[IN] !== NULL) | ||
{ | ||
$data[IN] = floatval(str_replace(",",".",$data[IN])); | ||
$data[IN] = $data[IN] * $multiplier; | ||
} | ||
if($data[OUT] !== NULL) | ||
{ | ||
$data[OUT] = floatval(str_replace(",",".",$data[OUT])); | ||
$data[OUT] = $data[OUT] * $multiplier; | ||
} | ||
| ||
debug ("RRD ReadData: Returning (".($data[IN]===NULL?'NULL':$data[IN]).",".($data[OUT]===NULL?'NULL':$data[OUT]).",$data_time)\n"); | ||
| ||
return( array($data[IN], $data[OUT], $data_time) ); | ||
} |
} | |
} |
} | |
|
| |
// vim:ts=4:sw=4: |
// vim:ts=4:sw=4: | |
?> |
?> |