Projet

Général

Profil

Télécharger (14,9 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / usr / local / www / graph.php @ 2d1e985d

1
<?php
2
/*
3
	graph.php
4
	part of m0n0wall (http://m0n0.ch/wall)
5
	
6
	Copyright (C) 2004-2006 T. Lechat <dev@lechat.org>, Manuel Kasper <mk@neon1.net>
7
	and Jonathan Watt <jwatt@jwatt.org>.
8
	All rights reserved.
9
	
10
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12
	
13
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15
	
16
	2. Redistributions in binary form must reproduce the above copyright
17
	   notice, this list of conditions and the following disclaimer in the
18
	   documentation and/or other materials provided with the distribution.
19
	
20
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
	POSSIBILITY OF SUCH DAMAGE.
30
*/
31
/*
32
	pfSense_MODULE:	graph
33
*/
34

    
35
##|+PRIV
36
##|*IDENT=page-diagnostics-interfacetraffic
37
##|*NAME=Diagnostics: Interface Traffic page
38
##|*DESCR=Allow access to the 'Diagnostics: Interface Traffic' page.
39
##|*MATCH=graph.php*
40
##|-PRIV
41

    
42
require("globals.inc");
43
require("guiconfig.inc");
44

    
45
header("Last-Modified: " . gmdate( "D, j M Y H:i:s" ) . " GMT" );
46
header("Expires: " . gmdate( "D, j M Y H:i:s", time() ) . " GMT" );
47
header("Cache-Control: no-store, no-cache, must-revalidate" ); // HTTP/1.1
48
header("Cache-Control: post-check=0, pre-check=0", FALSE );
49
header("Pragma: no-cache"); // HTTP/1.0
50
header("Content-type: image/svg+xml");
51

    
52
/********** HTTP GET Based Conf ***********/
53
$ifnum=@$_GET["ifnum"];  // BSD / SNMP interface name / number
54
$ifnum = get_real_interface($ifnum);
55
$ifname=@$_GET["ifname"]?$_GET["ifname"]:"Interface $ifnum";  //Interface name that will be showed on top right of graph
56

    
57
/********* Other conf *******/
58
if (isset($config["widgets"]["trafficgraphs"]["scale_type"]))
59
	$scale_type = $config["widgets"]["trafficgraphs"]["scale_type"];
60
else
61
	$scale_type = "up";
62

    
63
$nb_plot=120;                   //NB plot in graph
64
if ($_GET["timeint"])
65
	$time_interval = $_GET["timeint"];		//Refresh time Interval
66
else
67
	$time_interval = 3;
68

    
69
if ($_GET["initdelay"])
70
	$init_delay = $_GET["initdelay"];		//Initial Delay
71
else
72
	$init_delay = 3;
73

    
74
//SVG attributes
75
$attribs['axis']='fill="black" stroke="black"';
76
$attribs['in']='fill="#FF0000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="7"';
77
$attribs['out']='fill="#000000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="7"';
78
$attribs['graph_in']='fill="none" stroke="#FF0000" stroke-opacity="0.8"';
79
$attribs['graph_out']='fill="none" stroke="#000000" stroke-opacity="0.8"';
80
$attribs['legend']='fill="black" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4"';
81
$attribs['graphname']='fill="#FF0000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="8"';
82
$attribs['grid_txt']='fill="gray" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="6"';
83
$attribs['grid']='stroke="gray" stroke-opacity="0.5"';
84
$attribs['switch_unit']='fill="#FF0000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4" text-decoration="underline"';
85
$attribs['switch_scale']='fill="#FF0000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4" text-decoration="underline"';
86
$attribs['error']='fill="blue" font-family="Arial" font-size="4"';
87
$attribs['collect_initial']='fill="gray" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4"';
88

    
89
//Error text if we cannot fetch data : depends on which method is used
90
$error_text = "Cannot get data about interface " . htmlspecialchars($ifnum);
91

    
92
$height=100;            //SVG internal height : do not modify
93
$width=200;             //SVG internal width : do not modify
94

    
95
$fetch_link = "ifstats.php?if=" . htmlspecialchars($ifnum);
96

    
97
/* check for custom theme colors */
98
if(file_exists("/usr/local/www/themes/{$g['theme']}/graph.php")) {
99
	$themetxt = file_get_contents("/usr/local/www/themes/{$g['theme']}/graph.php");
100
	eval($themetxt);
101
} 
102

    
103
/********* Graph DATA **************/
104
print('<?xml version="1.0" encoding="iso-8859-1"?>' . "\n");?>
105
<svg width="100%" height="100%" viewBox="0 0 <?=$width?> <?=$height?>" preserveAspectRatio="none" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)">
106
  <g id="graph">
107
    <rect id="bg" x1="0" y1="0" width="100%" height="100%" fill="white"/>
108
    <line id="axis_x" x1="0" y1="0" x2="0" y2="100%" <?=$attribs['axis']?>/>
109
    <line id="axis_y" x1="0" y1="100%" x2="100%" y2="100%" <?=$attribs['axis']?>/>
110
    <path id="graph_out" d="M0 <?=$height?> L 0 <?=$height?>" <?=$attribs['graph_out']?>/>
111
    <path id="graph_in"  d="M0 <?=$height?> L 0 <?=$height?>" <?=$attribs['graph_in']?>/>
112
    <path id="grid"  d="M0 <?=$height/4*1?> L <?=$width?> <?=$height/4*1?> M0 <?=$height/4*2?> L <?=$width?> <?=$height/4*2?> M0 <?=$height/4*3?> L <?=$width?> <?=$height/4*3?>" <?=$attribs['grid']?>/>
113
    <text id="grid_txt1" x="<?=$width?>" y="<?=$height/4*1?>" <?=$attribs['grid_txt']?> text-anchor="end"> </text>
114
    <text id="grid_txt2" x="<?=$width?>" y="<?=$height/4*2?>" <?=$attribs['grid_txt']?> text-anchor="end"> </text>
115
    <text id="grid_txt3" x="<?=$width?>" y="<?=$height/4*3?>" <?=$attribs['grid_txt']?> text-anchor="end"> </text>
116
    <text id="graph_in_lbl" x="5" y="8" <?=$attribs['in']?>><?=gettext("In"); ?></text>
117
    <text id="graph_out_lbl" x="5" y="16" <?=$attribs['out']?>><?=gettext("Out"); ?></text>
118
    <text id="graph_in_txt" x="20" y="8" <?=$attribs['in']?>> </text>
119
    <text id="graph_out_txt" x="20" y="16" <?=$attribs['out']?>> </text>
120
    <text id="ifname" x="<?=$width?>" y="8" <?=$attribs['graphname']?> text-anchor="end"><?=htmlspecialchars($ifname)?></text>
121
    <text id="switch_unit" x="<?=$width*0.55?>" y="5" <?=$attribs['switch_unit']?>><?=gettext("Switch to bytes/s"); ?></text>
122
    <text id="switch_scale" x="<?=$width*0.55?>" y="11" <?=$attribs['switch_scale']?>><?=gettext("AutoScale"); ?> (<?=$scale_type?>)</text>
123
    <text id="datetime" x="<?=$width*0.33?>" y="5" <?=$attribs['legend']?>> </text>
124
    <text id="graphlast" x="<?=$width*0.55?>" y="17" <?=$attribs['legend']?>><?=gettext("Graph shows last"); ?> <?=$time_interval*$nb_plot?> <?=gettext("seconds"); ?></text>
125
    <polygon id="axis_arrow_x" <?=$attribs['axis']?> points="<?=($width) . "," . ($height)?> <?=($width-2) . "," . ($height-2)?> <?=($width-2) . "," . $height?>"/>
126
    <text id="error" x="<?=$width*0.5?>" y="<?=$height*0.5?>"  visibility="hidden" <?=$attribs['error']?> text-anchor="middle"><?=$error_text?></text>
127
    <text id="collect_initial" x="<?=$width*0.5?>" y="<?=$height*0.5?>"  visibility="hidden" <?=$attribs['collect_initial']?> text-anchor="middle"><?=gettext("Collecting initial data, please wait"); ?>...</text>
128
  </g>
129
  <script type="text/ecmascript">
130
    <![CDATA[
131

    
132
/**
133
 * getURL is a proprietary Adobe function, but it's simplicity has made it very
134
 * popular. If getURL is undefined we spin our own by wrapping XMLHttpRequest.
135
 */
136
if (typeof getURL == 'undefined') {
137
  getURL = function(url, callback) {
138
    if (!url)
139
      throw '<?=gettext("No URL for getURL"); ?>';
140

    
141
    try {
142
      if (typeof callback.operationComplete == 'function')
143
        callback = callback.operationComplete;
144
    } catch (e) {}
145
    if (typeof callback != 'function')
146
      throw '<?=gettext("No callback function for getURL"); ?>';
147

    
148
    var http_request = null;
149
    if (typeof XMLHttpRequest != 'undefined') {
150
      http_request = new XMLHttpRequest();
151
    }
152
    else if (typeof ActiveXObject != 'undefined') {
153
      try {
154
        http_request = new ActiveXObject('Msxml2.XMLHTTP');
155
      } catch (e) {
156
        try {
157
          http_request = new ActiveXObject('Microsoft.XMLHTTP');
158
        } catch (e) {}
159
      }
160
    }
161
    if (!http_request)
162
      throw '<?=gettext("Both getURL and XMLHttpRequest are undefined"); ?>';
163

    
164
    http_request.onreadystatechange = function() {
165
      if (http_request.readyState == 4) {
166
        callback( { success : true,
167
                    content : http_request.responseText,
168
                    contentType : http_request.getResponseHeader("Content-Type") } );
169
      }
170
    }
171
    http_request.open('GET', url, true);
172
    http_request.send(null);
173
  }
174
}
175

    
176
var SVGDoc = null;
177
var last_ifin = 0;
178
var last_ifout = 0;
179
var last_ugmt = 0;
180
var max = 0;
181
var plot_in = new Array();
182
var plot_out = new Array();
183

    
184
var max_num_points = <?=$nb_plot?>;  // maximum number of plot data points
185
var step = <?=$width?> / max_num_points ;
186
var unit = 'bits';
187
var scale_type = '<?=$scale_type?>';
188

    
189
function init(evt) {
190
  SVGDoc = evt.target.ownerDocument;
191
  SVGDoc.getElementById("switch_unit").addEventListener("mousedown", switch_unit, false);
192
  SVGDoc.getElementById("switch_scale").addEventListener("mousedown", switch_scale, false);
193

    
194
  fetch_data();
195
}
196

    
197
function switch_unit(event)
198
{
199
  SVGDoc.getElementById('switch_unit').firstChild.data = '<?=gettext("Switch to"); ?> ' + unit + '/s';
200
  unit = (unit == 'bits') ? 'bytes' : 'bits';
201
}
202

    
203
function switch_scale(event)
204
{
205
  scale_type = (scale_type == 'up') ? '<?=gettext("follow"); ?>' : '<?=gettext("up"); ?>';
206
  SVGDoc.getElementById('switch_scale').firstChild.data = 'AutoScale (' + scale_type + ')';
207
}
208

    
209
function fetch_data() {
210
  getURL('<?=$fetch_link?>', plot_data);
211
}
212

    
213
function plot_data(obj) {
214
  // Show datetimelegend
215
  var now = new Date();
216
  var datetime = (now.getMonth()+1) + "/" + now.getDate() + "/" + now.getFullYear() + ' ' + 
217
    LZ(now.getHours()) + ":" + LZ(now.getMinutes()) + ":" + LZ(now.getSeconds());
218
  SVGDoc.getElementById('datetime').firstChild.data = datetime;
219

    
220
  if (!obj.success)
221
    return handle_error();  // getURL failed to get data
222

    
223
  var t = obj.content.split("|");
224
  var ugmt = parseFloat(t[0]);  // ugmt is an unixtimestamp style
225
  var ifin = parseInt(t[1], 10);    // number of bytes received by the interface
226
  var ifout = parseInt(t[2], 10);   // number of bytes sent by the interface
227
  var scale;
228

    
229
  if (!isNumber(ifin) || !isNumber(ifout))
230
    return handle_error();
231

    
232
  var diff_ugmt  = ugmt - last_ugmt;
233
  var diff_ifin  = ifin - last_ifin;
234
  var diff_ifout = ifout - last_ifout;
235

    
236
  if (diff_ugmt == 0)
237
    diff_ugmt = 1;  /* avoid division by zero */
238

    
239
  last_ugmt = ugmt;
240
  last_ifin = ifin;
241
  last_ifout = ifout;
242
  var graphTimerId = 0;
243
  switch (plot_in.length) {
244
  	case 0:
245
  		SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'visible');
246
		plot_in[0] = diff_ifin / diff_ugmt;
247
		plot_out[0] = diff_ifout / diff_ugmt;
248
		setTimeout('fetch_data()',<?=1000*($time_interval + $init_delay)?>);
249
		return;
250
	case 1:
251
    	SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'hidden');
252
    	break;
253
    case max_num_points:
254
		// shift plot to left if the maximum number of plot points has been reached
255
		var i = 0;
256
		while (i < max_num_points) {
257
		  plot_in[i] = plot_in[i+1];
258
		  plot_out[i] = plot_out[++i];
259
		}
260
		plot_in.length--;
261
		plot_out.length--;
262
  }
263

    
264
  plot_in[plot_in.length] = diff_ifin / diff_ugmt;
265
  plot_out[plot_out.length]= diff_ifout / diff_ugmt;
266
  var index_plot = plot_in.length - 1;
267

    
268
  SVGDoc.getElementById('graph_in_txt').firstChild.data = formatSpeed(plot_in[index_plot], unit);
269
  SVGDoc.getElementById('graph_out_txt').firstChild.data = formatSpeed(plot_out[index_plot], unit);
270

    
271
  /* determine peak for sensible scaling */
272
  if (scale_type == 'up') {
273
    if (plot_in[index_plot] > max)
274
      max = plot_in[index_plot];
275
    if (plot_out[index_plot] > max)
276
      max = plot_out[index_plot];
277
  }
278
  else if (scale_type == 'follow') {
279
    i = 0;
280
    max = 0;
281
    while (i < plot_in.length) {
282
      if (plot_in[i] > max)
283
        max = plot_in[i];
284
      if (plot_out[i] > max)
285
        max = plot_out[i];
286
      i++;
287
    }
288
  }
289

    
290
  var rmax;  // max, rounded up
291

    
292
  if (unit == 'bits') {
293
    /* round up max, such that
294
         100 kbps -> 200 kbps -> 400 kbps -> 800 kbps -> 1 Mbps -> 2 Mbps -> ... */
295
    rmax = 12500;
296
    i = 0;
297
    while (max > rmax) {
298
      i++;
299
      if (i && (i % 4 == 0))
300
        rmax *= 1.25;
301
      else
302
        rmax *= 2;
303
    }
304
  } else {
305
    /* round up max, such that
306
         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 ... */
307
    rmax = 10240;
308
    i = 0;
309
    while (max > rmax) {
310
      i++;
311
      if (i && (i % 4 == 0))
312
        rmax *= 1.25;
313
      else
314
        rmax *= 2;
315
      
316
      if (i == 8)
317
        rmax *= 1.024;
318
    }
319
  }
320

    
321
  scale = <?=$height?> / rmax;
322

    
323
  /* change labels accordingly */
324
  SVGDoc.getElementById('grid_txt1').firstChild.data = formatSpeed(3*rmax/4,unit);
325
  SVGDoc.getElementById('grid_txt2').firstChild.data = formatSpeed(2*rmax/4,unit);
326
  SVGDoc.getElementById('grid_txt3').firstChild.data = formatSpeed(rmax/4,unit);
327

    
328
  var path_in = "M 0 " + (<?=$height?> - (plot_in[0] * scale));
329
  var path_out = "M 0 " + (<?=$height?> - (plot_out[0] * scale));
330
  for (i = 1; i < plot_in.length; i++)
331
  {
332
    var x = step * i;
333
    var y_in = <?=$height?> - (plot_in[i] * scale);
334
    var y_out = <?=$height?> - (plot_out[i] * scale);
335
    path_in += " L" + x + " " + y_in;
336
    path_out += " L" + x + " " + y_out;
337
  }
338

    
339
  SVGDoc.getElementById('error').setAttributeNS(null, 'visibility', 'hidden');
340
  SVGDoc.getElementById('graph_in').setAttributeNS(null, 'd', path_in);
341
  SVGDoc.getElementById('graph_out').setAttributeNS(null, 'd', path_out);
342

    
343
  setTimeout('fetch_data()',<?=1000*$time_interval?>);
344
}
345

    
346
function handle_error() {
347
  SVGDoc.getElementById("error").setAttributeNS(null, 'visibility', 'visible');
348
  setTimeout('fetch_data()',<?=1000*$time_interval?>);
349
}
350

    
351
function isNumber(a) {
352
  return typeof a == 'number' && isFinite(a);
353
}
354

    
355
function formatSpeed(speed, unit) {
356
  if (unit == 'bits')
357
    return formatSpeedBits(speed);
358
  if (unit == 'bytes')
359
    return formatSpeedBytes(speed);
360
}
361

    
362
function formatSpeedBits(speed) {
363
  // format speed in bits/sec, input: bytes/sec
364
  if (speed < 125000)
365
    return Math.round(speed / 125) + " <?=gettext("Kbps"); ?>";
366
  if (speed < 125000000)
367
    return Math.round(speed / 1250)/100 + " <?=gettext("Mbps"); ?>";
368
  // else
369
  return Math.round(speed / 1250000)/100 + " <?=gettext("Gbps"); ?>";  /* wow! */
370
}
371

    
372
function formatSpeedBytes(speed) {
373
  // format speed in bytes/sec, input:  bytes/sec
374
  if (speed < 1048576)
375
    return Math.round(speed / 10.24)/100 + " <?=gettext("KB/s"); ?>";
376
  if (speed < 1073741824)
377
    return Math.round(speed / 10485.76)/100 + " <?=gettext("MB/s"); ?>";
378
  // else
379
  return Math.round(speed / 10737418.24)/100 + " <?=gettext("GB/s"); ?>";  /* wow! */
380
}
381

    
382
function LZ(x) {
383
  return (x < 0 || x > 9 ? "" : "0") + x;
384
}
385

    
386
    ]]>
387
  </script>
388
</svg>
(82-82/246)