1 | <?php |
||
2 | |||
3 | /** |
||
4 | * LibreNMS |
||
5 | * |
||
6 | * This file is included with LibreNMS. It was originally part of m0n0wall <http://www.m0n0.ch/wall/> |
||
7 | * |
||
8 | * @author T. Lechat <[email protected]>, Manuel Kasper <[email protected]>, Jonathan Watt <[email protected]> |
||
9 | * @copyright 2004-2006 T. Lechat <[email protected]>, Manuel Kasper <[email protected]>, Jonathan Watt <[email protected]> |
||
10 | * @license BSD |
||
11 | */ |
||
12 | $init_modules = ['web', 'auth']; |
||
13 | require realpath(__DIR__ . '/..') . '/includes/init.php'; |
||
14 | |||
15 | if (is_numeric($_GET['id']) && (Config::get('allow_unauth_graphs') || port_permitted($_GET['id']))) { |
||
16 | $port = cleanPort(get_port_by_id($_GET['id'])); |
||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
17 | $device = device_by_id_cache($port['device_id']); |
||
18 | $title = generate_device_link($device); |
||
19 | $title .= ' :: Port ' . generate_port_link($port); |
||
20 | $auth = true; |
||
21 | } else { |
||
22 | echo 'Unauthenticad'; |
||
23 | exit; |
||
24 | } |
||
25 | |||
26 | header('Content-type: image/svg+xml'); |
||
27 | |||
28 | /********** HTTP GET Based Conf ***********/ |
||
29 | $ifnum = @$port['ifIndex']; // BSD / SNMP interface name / number |
||
30 | $ifname = $port['label']; //Interface name that will be showed on top right of graph |
||
31 | $hostname = shorthost($device['hostname']); |
||
32 | |||
33 | if ($_GET['title']) { |
||
34 | $ifname = \LibreNMS\Util\Clean::html($_GET['title'], []); |
||
35 | } |
||
36 | |||
37 | /********* Other conf *******/ |
||
38 | $scale_type = 'follow'; //Autoscale default setup : "up" = only increase scale; "follow" = increase and decrease scale according to current graphed datas |
||
39 | $nb_plot = 240; //NB plot in graph |
||
40 | |||
41 | if (is_numeric($_GET['interval'])) { |
||
42 | $time_interval = $_GET['interval']; |
||
43 | } else { |
||
44 | $time_interval = 1; //Refresh time Interval |
||
45 | } |
||
46 | |||
47 | $fetch_link = 'data.php?id=' . $_GET['id']; |
||
48 | |||
49 | //SVG attributes |
||
50 | $attribs['axis'] = 'fill="black" stroke="black"'; |
||
51 | $attribs['in'] = 'fill="green" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="7"'; |
||
52 | $attribs['out'] = 'fill="blue" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="7"'; |
||
53 | $attribs['graph_in'] = 'fill="none" stroke="green" stroke-opacity="0.8"'; |
||
54 | $attribs['graph_out'] = 'fill="none" stroke="blue" stroke-opacity="0.8"'; |
||
55 | $attribs['legend'] = 'fill="black" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4"'; |
||
56 | $attribs['cachewarning'] = 'fill="darkorange" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4"'; |
||
57 | $attribs['graphname'] = 'fill="#435370" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="9"'; |
||
58 | $attribs['hostname'] = 'fill="#435370" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="6"'; |
||
59 | $attribs['grid_txt'] = 'fill="gray" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="6"'; |
||
60 | $attribs['grid'] = 'stroke="gray" stroke-opacity="0.5"'; |
||
61 | $attribs['switch_unit'] = 'fill="#435370" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4" text-decoration="underline"'; |
||
62 | $attribs['switch_scale'] = 'fill="#435370" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4" text-decoration="underline"'; |
||
63 | $attribs['error'] = 'fill="blue" font-family="Arial" font-size="4"'; |
||
64 | $attribs['collect_initial'] = 'fill="gray" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4"'; |
||
65 | |||
66 | //Error text if we cannot fetch data : depends on which method is used |
||
67 | $error_text = "Cannot get data about interface $ifnum"; |
||
68 | |||
69 | $height = 125; //SVG internal height : do not modify |
||
70 | $width = 300; //SVG internal width : do not modify |
||
71 | |||
72 | /********* Graph DATA **************/ |
||
73 | echo '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n"; ?> |
||
74 | <svg width="100%" height="100%" viewBox="0 0 <?php echo "$width $height" ?>" preserveAspectRatio="none" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" |
||
75 | onload="init(evt)"> |
||
76 | <g id="graph"> |
||
77 | <rect id="bg" x1="0" y1="0" width="100%" height="100%" fill="white"/> |
||
78 | <line id="axis_x" x1="0" y1="0" x2="0" y2="100%" <?php echo $attribs['axis'] ?>/> |
||
79 | <line id="axis_y" x1="0" y1="100%" x2="100%" y2="100%" <?php echo $attribs['axis'] ?>/> |
||
80 | <path id="graph_out" d="M0 <?php echo $height ?> L 0 <?php echo $height . '" ' . $attribs['graph_out'] ?>/> |
||
81 | <path id="graph_in" d="M0 <?php echo $height ?> L 0 <?php echo $height . '" ' . $attribs['graph_in'] ?>/> |
||
82 | <path id="grid" d="M0 <?php echo $height / 4 * 1 ?> L <?php echo $width ?> <?php echo $height / 4 * 1 ?> M0 <?php echo $height / 4 * 2 ?> L <?php echo $width ?> <?php echo $height / 4 * 2 ?> M0 <?php echo $height / 4 * 3 ?> L <?php echo $width . ' ' . ($height / 4 * 3) ?>" <?php echo $attribs['grid']?>/> |
||
83 | <text id="grid_txt1" x="<?php echo $width ?>" y="<?php echo $height / 4 * 1 ?>" <?php echo $attribs['grid_txt'] ?> text-anchor="end"> </text> |
||
84 | <text id="grid_txt2" x="<?php echo $width ?>" y="<?php echo $height / 4 * 2 ?>" <?php echo $attribs['grid_txt'] ?> text-anchor="end"> </text> |
||
85 | <text id="grid_txt3" x="<?php echo $width ?>" y="<?php echo $height / 4 * 3 ?>" <?php echo $attribs['grid_txt'] ?> text-anchor="end"> </text> |
||
86 | <text id="graph_in_lbl" x="5" y="8" <?php echo $attribs['in'] ?>>In</text> |
||
87 | <text id="graph_out_lbl" x="5" y="16" <?php echo $attribs['out'] ?>>Out</text> |
||
88 | <text id="graph_in_txt" x="20" y="8" <?php echo $attribs['in'] ?>> </text> |
||
89 | <text id="graph_out_txt" x="20" y="16" <?php echo $attribs['out'] ?>> </text> |
||
90 | <text id="ifname" x="<?php echo $width - 2 ?>" y="8" <?php echo $attribs['graphname'] ?> text-anchor="end"><?php echo $ifname ?></text> |
||
91 | <text id="hostname" x="<?php echo $width - 2 ?>" y="14" <?php echo $attribs['hostname'] ?> text-anchor="end"><?php echo $hostname ?></text> |
||
92 | <text id="switch_unit" x="<?php echo $width * 0.48 ?>" y="5" <?php echo $attribs['switch_unit'] ?>>Switch to bytes/s</text> |
||
93 | <text id="switch_scale" x="<?php echo $width * 0.48 ?>" y="11" <?php echo $attribs['switch_scale'] ?>>AutoScale (<?php echo $scale_type ?>)</text> |
||
94 | <text id="datetime" x="<?php echo $width * 0.33 ?>" y="5" <?php echo $attribs['legend'] ?>> </text> |
||
95 | <text id="graphlast" x="<?php echo $width * 0.48 ?>" y="17" <?php echo $attribs['legend'] ?>>Graph shows last <?php echo $time_interval * $nb_plot ?> seconds</text> |
||
96 | <text id="cachewarning" x="<?php echo $width * 0.48 ?>" y="22" <?php echo $attribs['cachewarning'] ?> visibility="hidden">Caching may be in effect (<tspan id="cacheinterval">?</tspan>s)</text> |
||
97 | <polygon id="axis_arrow_x" <?php echo $attribs['axis'] ?> points="<?php echo $width . ',' . $height ?> <?php echo($width - 2) . ',' . ($height - 2) ?> <?php echo($width - 2) . ',' . $height ?>"/> |
||
98 | <text id="error" x="<?php echo $width * 0.5 ?>" y="<?php echo $height * 0.5 ?>" visibility="hidden" <?php echo $attribs['error'] ?> text-anchor="middle"><?php echo $error_text ?></text> |
||
99 | <text id="collect_initial" x="<?php echo $width * 0.5 ?>" y="<?php echo $height * 0.5 ?>" visibility="hidden" <?php echo $attribs['collect_initial'] ?> text-anchor="middle">Collecting initial data, please wait...</text> |
||
100 | </g> |
||
101 | <script type="text/ecmascript"> |
||
102 | <![CDATA[ |
||
103 | |||
104 | /** |
||
105 | * getURL is a proprietary Adobe function, but it's simplicity has made it very |
||
106 | * popular. If getURL is undefined we spin our own by wrapping XMLHttpRequest. |
||
107 | */ |
||
108 | if (typeof getURL == 'undefined') { |
||
109 | getURL = function(url, callback) { |
||
110 | if (!url) |
||
111 | throw 'No URL for getURL'; |
||
112 | |||
113 | try { |
||
114 | if (typeof callback.operationComplete == 'function') |
||
115 | callback = callback.operationComplete; |
||
116 | } catch (e) {} |
||
117 | if (typeof callback != 'function') |
||
118 | throw 'No callback function for getURL'; |
||
119 | |||
120 | var http_request = null; |
||
121 | if (typeof XMLHttpRequest != 'undefined') { |
||
122 | http_request = new XMLHttpRequest(); |
||
123 | } |
||
124 | else if (typeof ActiveXObject != 'undefined'){ |
||
125 | try { |
||
126 | http_request = new ActiveXObject('Msxml2.XMLHTTP'); |
||
127 | } catch (e) { |
||
128 | try { |
||
129 | http_request = new ActiveXObject('Microsoft.XMLHTTP'); |
||
130 | } catch (e) {} |
||
131 | } |
||
132 | } |
||
133 | if (!http_request) |
||
134 | throw 'Both getURL and XMLHttpRequest are undefined'; |
||
135 | |||
136 | http_request.onreadystatechange = function() { |
||
137 | if (http_request.readyState == 4) { |
||
138 | callback( { success : true, |
||
139 | content : http_request.responseText, |
||
140 | contentType : http_request.getResponseHeader("Content-Type") } ); |
||
141 | } |
||
142 | } |
||
143 | http_request.open('GET', url, true); |
||
144 | http_request.send(null); |
||
145 | } |
||
146 | } |
||
147 | |||
148 | var SVGDoc = null; |
||
149 | var last_ifin = 0; |
||
150 | var last_ifout = 0; |
||
151 | var last_ugmt = 0; |
||
152 | var last_real = 0; |
||
153 | var real_interval = 0; |
||
154 | var max = 0; |
||
155 | var plot_in = []; |
||
156 | var plot_out = []; |
||
157 | |||
158 | var max_num_points = <?php echo $nb_plot ?>; // maximum number of plot data points |
||
159 | var step = <?php echo $width ?> / max_num_points ; |
||
160 | var unit = 'bits'; |
||
161 | var scale_type = '<?php echo $scale_type ?>'; |
||
162 | |||
163 | function init(evt) { |
||
164 | SVGDoc = evt.target.ownerDocument; |
||
165 | SVGDoc.getElementById("switch_unit").addEventListener("mousedown", switch_unit, false); |
||
166 | SVGDoc.getElementById("switch_scale").addEventListener("mousedown", switch_scale, false); |
||
167 | |||
168 | fetch_data(); |
||
169 | } |
||
170 | |||
171 | function switch_unit(event) |
||
172 | { |
||
173 | SVGDoc.getElementById('switch_unit').firstChild.data = 'Switch to ' + unit + '/s'; |
||
174 | unit = (unit == 'bits') ? 'bytes' : 'bits'; |
||
175 | } |
||
176 | |||
177 | function switch_scale(event) |
||
178 | { |
||
179 | scale_type = (scale_type == 'up') ? 'follow' : 'up'; |
||
180 | SVGDoc.getElementById('switch_scale').firstChild.data = 'AutoScale (' + scale_type + ')'; |
||
181 | } |
||
182 | |||
183 | function fetch_data() { |
||
184 | getURL('<?php echo $fetch_link ?>', plot_data); |
||
185 | } |
||
186 | |||
187 | function plot_data(obj) { |
||
188 | // Show datetimelegend |
||
189 | var now = new Date(); |
||
190 | var datetime = (now.getMonth()+1) + "/" + now.getDate() + "/" + now.getFullYear() + ' ' + |
||
191 | LZ(now.getHours()) + ":" + LZ(now.getMinutes()) + ":" + LZ(now.getSeconds()); |
||
192 | SVGDoc.getElementById('datetime').firstChild.data = datetime; |
||
193 | |||
194 | if (!obj.success) |
||
195 | return handle_error(); // getURL failed to get data |
||
196 | |||
197 | var t = obj.content.split("|"); |
||
198 | var ugmt = parseFloat(t[0]); // ugmt is an unixtimestamp style |
||
199 | var ifin = parseInt(t[1]); // number of bytes received by the interface |
||
200 | var ifout = parseInt(t[2]); // number of bytes sent by the interface |
||
201 | var scale; |
||
202 | |||
203 | if (!isNumber(ifin) || !isNumber(ifout)) |
||
204 | return handle_error(); |
||
205 | |||
206 | var diff_ugmt = ugmt - last_ugmt; |
||
207 | var diff_ifin = ifin - last_ifin; |
||
208 | var diff_ifout = ifout - last_ifout; |
||
209 | |||
210 | if (diff_ifin === 0 && diff_ifout === 0) { |
||
211 | handle_error('cachewarning'); |
||
212 | } else { |
||
213 | var diff_real = ugmt - last_real; |
||
214 | last_real = ugmt; |
||
215 | if (real_interval === 0) { |
||
216 | if (diff_real < 10000) { |
||
217 | real_interval = diff_real; |
||
218 | } |
||
219 | } else { |
||
220 | // running average to smooth out the numbers a bit |
||
221 | real_interval = (diff_real + real_interval) / 2; |
||
222 | } |
||
223 | } |
||
224 | |||
225 | if (diff_ugmt == 0) |
||
226 | diff_ugmt = 1; /* avoid division by zero */ |
||
227 | |||
228 | last_ugmt = ugmt; |
||
229 | last_ifin = ifin; |
||
230 | last_ifout = ifout; |
||
231 | |||
232 | switch (plot_in.length) { |
||
233 | case 0: |
||
234 | SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'visible'); |
||
235 | plot_in[0] = diff_ifin / diff_ugmt; |
||
236 | plot_out[0] = diff_ifout / diff_ugmt; |
||
237 | setTimeout('fetch_data()',<?php echo 1000 * $time_interval ?>); |
||
238 | return; |
||
239 | case 1: |
||
240 | SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'hidden'); |
||
241 | break; |
||
242 | case max_num_points: |
||
243 | // shift plot to left if the maximum number of plot points has been reached |
||
244 | plot_in.shift(); |
||
245 | plot_out.shift(); |
||
246 | } |
||
247 | |||
248 | var current_in = diff_ifin / diff_ugmt; |
||
249 | var current_out = diff_ifout / diff_ugmt; |
||
250 | plot_in.push(current_in); |
||
251 | plot_out.push(current_out); |
||
252 | |||
253 | if (current_in !== 0 && current_out !== 0) { |
||
254 | SVGDoc.getElementById('graph_in_txt').firstChild.data = formatSpeed(current_in, unit); |
||
255 | SVGDoc.getElementById('graph_out_txt').firstChild.data = formatSpeed(current_out, unit); |
||
256 | } |
||
257 | |||
258 | /* determine peak for sensible scaling */ |
||
259 | if (scale_type == 'up') { |
||
260 | if (current_in > max) |
||
261 | max = current_in; |
||
262 | if (current_out > max) |
||
263 | max = current_out; |
||
264 | } |
||
265 | else if (scale_type == 'follow') { |
||
266 | i = 0; |
||
267 | max = 0; |
||
268 | while (i < plot_in.length) { |
||
269 | if (plot_in[i] > max) |
||
270 | max = plot_in[i]; |
||
271 | if (plot_out[i] > max) |
||
272 | max = plot_out[i]; |
||
273 | i++; |
||
274 | } |
||
275 | } |
||
276 | |||
277 | var rmax; // max, rounded up |
||
278 | |||
279 | if (unit == 'bits') { |
||
280 | /* round up max, such that |
||
281 | 100 kbps -> 200 kbps -> 400 kbps -> 800 kbps -> 1 Mbps -> 2 Mbps -> ... */ |
||
282 | rmax = 12500; |
||
283 | i = 0; |
||
284 | while (max > rmax) { |
||
285 | i++; |
||
286 | if (i && (i % 4 == 0)) |
||
287 | rmax *= 1.25; |
||
288 | else |
||
289 | rmax *= 2; |
||
290 | } |
||
291 | } else { |
||
292 | /* round up max, such that |
||
293 | 10 KB/s -> 20 KB/s -> 40 KB/s -> 80 KB/s -> 100 KB/s -> 200 KB/s -> 400 KB/s -> 800 KB/s -> 1 MB/s ... */ |
||
294 | rmax = 10240; |
||
295 | i = 0; |
||
296 | while (max > rmax) { |
||
297 | i++; |
||
298 | if (i && (i % 4 == 0)) |
||
299 | rmax *= 1.25; |
||
300 | else |
||
301 | rmax *= 2; |
||
302 | |||
303 | if (i == 8) |
||
304 | rmax *= 1.024; |
||
305 | } |
||
306 | } |
||
307 | |||
308 | scale = <?php echo $height ?> / rmax; |
||
309 | |||
310 | /* change labels accordingly */ |
||
311 | SVGDoc.getElementById('grid_txt1').firstChild.data = formatSpeed(3*rmax/4,unit); |
||
312 | SVGDoc.getElementById('grid_txt2').firstChild.data = formatSpeed(2*rmax/4,unit); |
||
313 | SVGDoc.getElementById('grid_txt3').firstChild.data = formatSpeed(rmax/4,unit); |
||
314 | |||
315 | var path_in = "M 0 " + (<?php echo $height ?> - (plot_in[0] * scale)); |
||
316 | var path_out = "M 0 " + (<?php echo $height ?> - (plot_out[0] * scale)); |
||
317 | for (i = 1; i < plot_in.length; i++) |
||
318 | { |
||
319 | var x = step * i; |
||
320 | if (plot_in[i] !== 0 && plot_out[i] !== 0) { |
||
321 | var y_in = <?php echo $height ?> - (plot_in[i] * scale); |
||
322 | var y_out = <?php echo $height ?> - (plot_out[i] * scale); |
||
323 | path_in += " L" + x + " " + y_in; |
||
324 | path_out += " L" + x + " " + y_out; |
||
325 | } |
||
326 | } |
||
327 | |||
328 | SVGDoc.getElementById('error').setAttributeNS(null, 'visibility', 'hidden'); |
||
329 | SVGDoc.getElementById('graph_in').setAttributeNS(null, 'd', path_in); |
||
330 | SVGDoc.getElementById('graph_out').setAttributeNS(null, 'd', path_out); |
||
331 | |||
332 | setTimeout('fetch_data()',<?php echo 1000 * $time_interval ?>); |
||
333 | } |
||
334 | |||
335 | function handle_error(type) { |
||
336 | if (type === 'cachewarning') { |
||
337 | SVGDoc.getElementById("cachewarning").setAttributeNS(null, 'visibility', 'visible'); |
||
338 | if (real_interval !== 0) { |
||
339 | SVGDoc.getElementById('cacheinterval').firstChild.data = Math.round(real_interval); |
||
340 | } |
||
341 | return; |
||
342 | } else { |
||
343 | SVGDoc.getElementById("error").setAttributeNS(null, 'visibility', 'visible'); |
||
344 | } |
||
345 | setTimeout('fetch_data()',<?php echo 1000 * $time_interval ?>); |
||
346 | } |
||
347 | |||
348 | function isNumber(a) { |
||
349 | return typeof a == 'number' && isFinite(a); |
||
350 | } |
||
351 | |||
352 | function formatSpeed(speed, unit) { |
||
353 | if (unit == 'bits') |
||
354 | return formatSpeedBits(speed); |
||
355 | if (unit == 'bytes') |
||
356 | return formatSpeedBytes(speed); |
||
357 | } |
||
358 | |||
359 | function formatSpeedBits(speed) { |
||
360 | // format speed in bits/sec, input: bytes/sec |
||
361 | if (speed < 125000) |
||
362 | return Math.round(speed / 125) + " Kbps"; |
||
363 | if (speed < 125000000) |
||
364 | return Math.round(speed / 1250)/100 + " Mbps"; |
||
365 | // else |
||
366 | return Math.round(speed / 1250000)/100 + " Gbps"; /* wow! */ |
||
367 | } |
||
368 | |||
369 | function formatSpeedBytes(speed) { |
||
370 | // format speed in bytes/sec, input: bytes/sec |
||
371 | if (speed < 1048576) |
||
372 | return Math.round(speed / 10.24)/100 + " KB/s"; |
||
373 | if (speed < 1073741824) |
||
374 | return Math.round(speed / 10485.76)/100 + " MB/s"; |
||
375 | // else |
||
376 | return Math.round(speed / 10737418.24)/100 + " GB/s"; /* wow! */ |
||
377 | } |
||
378 | |||
379 | function LZ(x) { |
||
380 | return (x < 0 || x > 9 ? "" : "0") + x; |
||
381 | } |
||
382 | |||
383 | ]]> |
||
384 | </script> |
||
385 | </svg> |
||
386 |