weathermap |
Subversion Repositories: |
Line No. | Rev | Author | Line |
---|---|---|---|
1 | 1 | simandl | <?php |
2 | // RRDtool datasource plugin. |
||
3 | // gauge:filename.rrd:ds_in:ds_out |
||
4 | // filename.rrd:ds_in:ds_out |
||
5 | // filename.rrd:ds_in:ds_out |
||
6 | // |
||
7 | class WeatherMapDataSource_rrd extends WeatherMapDataSource { |
||
8 | |
||
9 | function Init(&$map) |
||
10 | { |
||
11 | if (file_exists($map->rrdtool)) { |
||
12 | if((function_exists('is_executable')) && (!is_executable($map->rrdtool))) |
||
13 | { |
||
14 | warn("RRD DS: RRDTool exists but is not executable?\n"); |
||
15 | return(FALSE); |
||
16 | } |
||
17 | $map->rrdtool_check="FOUND"; |
||
18 | return(TRUE); |
||
19 | } |
||
20 | // normally, DS plugins shouldn't really pollute the logs |
||
21 | // this particular one is important to most users though... |
||
22 | if($map->context=='cli') |
||
23 | { |
||
24 | warn("RRD DS: Can't find RRDTOOL. Check line 29 of the 'weathermap' script.\nRRD-based TARGETs will fail.\n"); |
||
25 | } |
||
26 | if($map->context=='cacti') |
||
27 | { // unlikely to ever occur |
||
28 | warn("RRD DS: Can't find RRDTOOL. Check your Cacti config.\n"); |
||
29 | } |
||
30 | |
||
31 | return(FALSE); |
||
32 | } |
||
33 | |
||
34 | function Recognise($targetstring) |
||
35 | { |
||
36 | if(preg_match("/^(.*\.rrd):([\-a-zA-Z0-9_]+):([\-a-zA-Z0-9_]+)$/",$targetstring,$matches)) |
||
37 | { |
||
38 | return TRUE; |
||
39 | } |
||
40 | elseif(preg_match("/^(.*\.rrd)$/",$targetstring,$matches)) |
||
41 | { |
||
42 | return TRUE; |
||
43 | } |
||
44 | else |
||
45 | { |
||
46 | return FALSE; |
||
47 | } |
||
48 | } |
||
49 | |
||
50 | // Actually read data from a data source, and return it |
||
51 | // returns a 3-part array (invalue, outvalue and datavalid time_t) |
||
52 | // invalue and outvalue should be -1,-1 if there is no valid data |
||
53 | // data_time is intended to allow more informed graphing in the future |
||
54 | function ReadData($targetstring, &$map, &$item) |
||
55 | { |
||
56 | $in_ds = "traffic_in"; |
||
57 | $out_ds = "traffic_out"; |
||
58 | $rrdfile = $targetstring; |
||
59 | |
||
60 | $multiplier = 8; |
||
61 | |
||
62 | $inbw=-1; |
||
63 | $outbw=-1; |
||
64 | $data_time = 0; |
||
65 | |
||
66 | if(preg_match("/^(.*\.rrd):([\-a-zA-Z0-9_]+):([\-a-zA-Z0-9_]+)$/",$targetstring,$matches)) |
||
67 | { |
||
68 | $in_ds = $matches[2]; |
||
69 | $out_ds = $matches[3]; |
||
70 | $rrdfile = $matches[1]; |
||
71 | debug("Special DS names seen ($in_ds and $out_ds).\n"); |
||
72 | } |
||
73 | |
||
74 | if(preg_match("/^rrd:(.*)/",$rrdfile,$matches)) |
||
75 | { |
||
76 | $rrdfile = $matches[1]; |
||
77 | } |
||
78 | |
||
79 | if(preg_match("/^gauge:(.*)/",$rrdfile,$matches)) |
||
80 | { |
||
81 | $rrdfile = $matches[1]; |
||
82 | $multiplier = 1; |
||
83 | } |
||
84 | |
||
85 | |
||
86 | // we get the last 800 seconds of data - this might be 1 or 2 lines, depending on when in the |
||
87 | // cacti polling cycle we get run. This ought to stop the 'some lines are grey' problem that some |
||
88 | // people were seeing |
||
89 | |
||
90 | // $item->add_note("rrdversion","1.3"); |
||
91 | |
||
92 | if(file_exists($rrdfile)) |
||
93 | { |
||
94 | if(1==1) |
||
95 | { |
||
96 | debug ("RRD ReadData: Target DS names are $in_ds and $out_ds\n"); |
||
97 | |
||
98 | $period = intval($map->get_hint('rrd_period')); |
||
99 | if($period == 0) $period = 800; |
||
100 | $start = $map->get_hint('rrd_start'); |
||
101 | if($start == '') { |
||
102 | $start = "now-$period"; |
||
103 | $end = "now"; |
||
104 | } |
||
105 | else |
||
106 | { |
||
107 | $end = "start+".$period; |
||
108 | } |
||
109 | |
||
110 | $command = '"'.$map->rrdtool . '" fetch "'.$rrdfile.'" AVERAGE --start '.$start.' --end '.$end; |
||
111 | $command=$map->rrdtool . " fetch $rrdfile AVERAGE --start $start --end $end"; |
||
112 | |
||
113 | debug ("RRD ReadData: Running: $command\n"); |
||
114 | $pipe=popen($command, "r"); |
||
115 | |
||
116 | $lines=array (); |
||
117 | $count = 0; |
||
118 | $linecount = 0; |
||
119 | |
||
120 | if (isset($pipe)) |
||
121 | { |
||
122 | $headings=fgets($pipe, 4096); |
||
123 | fgets($pipe, 4096); // skip the blank line |
||
124 | $buffer=''; |
||
125 | |
||
126 | while (!feof($pipe)) |
||
127 | { |
||
128 | $line=fgets($pipe, 4096); |
||
129 | debug ("> " . $line); |
||
130 | $buffer.=$line; |
||
131 | $lines[]=$line; |
||
132 | $linecount++; |
||
133 | } |
||
134 | pclose ($pipe); |
||
135 | |
||
136 | debug("RRD ReadData: Read $linecount lines from rrdtool\n"); |
||
137 | |
||
138 | $rlines=array_reverse($lines); |
||
139 | $gotline=0; |
||
140 | $theline=''; |
||
141 | |
||
142 | foreach ($rlines as $line) |
||
143 | { |
||
144 | debug ("--" . $line . "\n"); |
||
145 | $cols=preg_split("/\s+/", $line); |
||
146 | $dataok=1; |
||
147 | $ii=0; |
||
148 | |
||
149 | foreach ($cols as $col) |
||
150 | { |
||
151 | # if( ! is_numeric($col) ) { $dataok=0; } |
||
152 | if (trim($col) != '' && !preg_match('/^\d+\.?\d*e?[+-]?\d*:?$/i', $col)) |
||
153 | { |
||
154 | $dataok=0; |
||
155 | debug ("RRD ReadData: $ii: This isn't a number: [$col]\n"); |
||
156 | } |
||
157 | |
||
158 | # if($col=='nan') { $dataok=0; } |
||
159 | $ii++; |
||
160 | } |
||
161 | |
||
162 | if ($gotline == 0 && $dataok == 1 && trim($line) != '') |
||
163 | { |
||
164 | debug ("RRD ReadData: Found a good line: $line ($headings)\n"); |
||
165 | $theline=$line; |
||
166 | $gotline=1; |
||
167 | $countwas=$count; |
||
168 | } |
||
169 | |
||
170 | $count++; |
||
171 | } |
||
172 | } |
||
173 | else |
||
174 | { |
||
175 | warn("RRD ReadData: failed to open pipe to RRDTool: ".$php_errormsg."\n"); |
||
176 | } |
||
177 | |
||
178 | if ($theline != '') |
||
179 | { |
||
180 | if ($countwas > 2) { warn |
||
181 | ("RRD ReadData: Data is not most recent entry ($countwas) for link: $targetstring\n"); } |
||
182 | |
||
183 | debug ("RRD ReadData: Our line is $theline\n"); |
||
184 | $cols=preg_split("/\s+/", $theline); |
||
185 | // this replace fudges 1.2.x output to look like 1.0.x |
||
186 | // then we can treat them both the same. |
||
187 | $heads=preg_split("/\s+/", preg_replace("/^\s+/","timestamp ",$headings) ); |
||
188 | |
||
189 | # $values = array_combine($heads,$cols); |
||
190 | for ($i=0, $cnt=count($cols); $i < $cnt; $i++) { $values[$heads[$i]] = $cols[$i]; } |
||
191 | |
||
192 | // as long as no-one actually manages to create an RRD with a DS of '-', then this will just fall through to 0 for '-' |
||
193 | if( isset($values[$in_ds]) || isset($values[$out_ds]) ) |
||
194 | { |
||
195 | $inbw=0; $outbw=0; |
||
196 | if(isset($values[$in_ds]) ) $inbw=$values[$in_ds] * $multiplier; |
||
197 | if(isset($values[$out_ds]) ) $outbw=$values[$out_ds] * $multiplier; |
||
198 | $data_time = $values['timestamp']; |
||
199 | $data_time = preg_replace("/:/","",$data_time); |
||
200 | } |
||
201 | else |
||
202 | { |
||
203 | 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?"); |
||
204 | } |
||
205 | } |
||
206 | } |
||
207 | } |
||
208 | else |
||
209 | { |
||
210 | warn ("Target $rrdfile doesn't exist. Is it a file?\n"); |
||
211 | } |
||
212 | |
||
213 | debug ("RRD ReadData: Returning ($inbw,$outbw,$data_time)\n"); |
||
214 | |
||
215 | return( array($inbw, $outbw, $data_time) ); |
||
216 | } |
||
217 | } |
||
218 | |
||
219 | // vim:ts=4:sw=4: |
||
220 | ?> |