Project

General

Profile

Download (12.2 KB) Statistics
| Branch: | Tag: | Revision:
1 5b237745 Scott Ullrich
#!/usr/local/bin/php -f
2
<?php
3
/*
4
	graph.php
5 16d9e6e4 Scott Ullrich
	Copyright (C) 2004 Scott Ullrich
6
	originally part of m0n0wall (http://m0n0.ch/wall)
7 5b237745 Scott Ullrich
	Copyright (C) 2004 T. Lechat <dev@lechat.org> and Manuel Kasper <mk@neon1.net>.
8
	All rights reserved.
9 66f8696f Scott Ullrich
10 5b237745 Scott Ullrich
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12 66f8696f Scott Ullrich
13 5b237745 Scott Ullrich
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15 66f8696f Scott Ullrich
16 5b237745 Scott Ullrich
	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 66f8696f Scott Ullrich
20 5b237745 Scott Ullrich
	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
// VERSION 1.0.4
33
34
/********** HTTP GET Based Conf ***********/
35
$ifnum=@$_GET["ifnum"];							//BSD / SNMP interface name / number
36
$ifname=@$_GET["ifname"]?$_GET["ifname"]:"Interface $ifnum";		//Interface name that will be showed on top right of graph
37
38
/********* Other conf *******/
39
$scale_type="up";		//Autoscale default setup : "up" = only increase scale; "follow" = increase and decrease scale according to current graphed datas
40
$nb_plot=120;			//NB plot in graph
41
$time_interval=1;		//Refresh time Interval
42
$first_stage_time_interval=2;	//First stage time Intervall
43
44
$urldata=@$_SERVER["SCRIPT_NAME"];
45
$fetch_link = "ifstats.cgi?$ifnum";
46
47
//Style
48
$style['bg']="fill:white;stroke:none;stroke-width:0;opacity:1;";
49
$style['axis']="fill:black;stroke:black;stroke-width:1;";
50 66f8696f Scott Ullrich
$style['in']="fill:#CC0000; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:7;";
51
$style['out']="fill:#000000; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:7;";
52
$style['graph_in']="fill:none;stroke:#CC0000;stroke-width:1;opacity:0.8;";
53
$style['graph_out']="fill:none;stroke:#000000;stroke-width:1;opacity:0.8;";
54 5b237745 Scott Ullrich
$style['legend']="fill:black; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4;";
55 66f8696f Scott Ullrich
$style['graphname']="fill:#CC0000; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:8;";
56 5b237745 Scott Ullrich
$style['grid_txt']="fill:gray; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:6;";
57
$style['grid']="stroke:gray;stroke-width:1;opacity:0.5;";
58 66f8696f Scott Ullrich
$style['switch_unit']="fill:#CC0000; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4; text-decoration:underline;";
59
$style['switch_scale']="fill:#CC0000; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4; text-decoration:underline;";
60 5b237745 Scott Ullrich
$style['error']="fill:blue; font-family:Arial; font-size:4;";
61
$style['collect_initial']="fill:gray; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4;";
62
63
//Error text if we cannot fetch data : depends on which method is used
64
$error_text = "Cannot get data about interface $ifnum";
65
66
$height=100;		//SVG internal height : do not modify
67
$width=200;		//SVG internal width : do not modify
68
69
/********* Graph DATA **************/
70
header("Content-type: image/svg+xml");
71
print('<?xml version="1.0" encoding="iso-8859-1"?>' . "\n");?><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)">
72
<g id="graph" style="visibility:visible">
73
	<rect id="bg" x1="0" y1="0" x2="<?=$width?>" y2="<?=$height?>" style="<?=$style['bg']?>"/>
74
	<line id="axis_x" x1="0" y1="0" x2="0" y2="<?=$height?>" style="<?=$style['axis']?>"/>
75
	<line id="axis_y" x1="0" y1="<?=$height?>" x2="<?=$width?>" y2="<?=$height?>" style="<?=$style['axis']?>"/>
76
	<path id="graph_out" d="M0 <?=$height?> L 0 <?=$height?>" style="<?=$style['graph_out']?>"/>
77
	<path id="graph_in"  d="M0 <?=$height?> L 0 <?=$height?>" style="<?=$style['graph_in']?>"/>
78
	<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?>" style="<?=$style[grid]?>"/>
79
	<text id="grid_txt1" x="<?=$width?>" y="<?=$height/4*1?>" style="<?=$style['grid_txt']?> text-anchor:end"> </text>
80
	<text id="grid_txt2" x="<?=$width?>" y="<?=$height/4*2?>" style="<?=$style['grid_txt']?> text-anchor:end"> </text>
81
	<text id="grid_txt3" x="<?=$width?>" y="<?=$height/4*3?>" style="<?=$style['grid_txt']?> text-anchor:end"> </text>
82
	<text id="graph_in_lbl" x="5" y="8" style="<?=$style['in']?>">In</text>
83
	<text id="graph_out_lbl" x="5" y="16" style="<?=$style['out']?> ">Out</text>
84
	<text id="graph_in_txt" x="20" y="8" style="<?=$style['in']?>"> </text>
85
	<text id="graph_out_txt" x="20" y="16" style="<?=$style['out']?> "> </text>
86
	<text id="ifname" x="<?=$width?>" y="8" style="<?=$style['graphname']?> text-anchor:end"><?=$ifname?></text>
87
	<text id="switch_unit" x="<?=$width*0.55?>" y="5" style="<?=$style['switch_unit']?>">Switch to bytes/s</text>
88
	<text id="switch_scale" x="<?=$width*0.55?>" y="11" style="<?=$style['switch_scale']?>">AutoScale (<?=$scale_type?>)</text>
89
	<text id="datetime" x="<?=$width*0.33?>" y="5" style="<?=$style['legend']?>"> </text>
90
	<text id="graphlast" x="<?=$width*0.55?>" y="17" style="<?=$style['legend']?>">Graph shows last <?=$time_interval*$nb_plot?> seconds</text>
91
	<polygon id="axis_arrow_x" style="<?=$style['axis']?>" points="<?=($width) . "," . ($height)?> <?=($width-2) . "," . ($height-2)?> <?=($width-2) . "," . $height?>"/>
92
	<text id="error" x="<?=$width*0.5?>" y="<?=$height*0.5?>"  style="visibility:hidden;<?=$style['error']?> text-anchor:middle"><?=$error_text?></text>
93
	<text id="collect_initial" x="<?=$width*0.5?>" y="<?=$height*0.5?>"  style="visibility:hidden;<?=$style['collect_initial']?> text-anchor:middle">Collecting initial data, please wait...</text>
94
</g>
95
96
<script type="text/ecmascript"><![CDATA[
97
var SVGDoc;
98
var last_ifin=0;
99
var last_ifout=0;
100
var last_ugmt=0;
101
var diff_ugmt=0;
102
var diff_ifin=0;
103
var diff_ifout=0;
104
var max = 0;
105
plot_in=new Array();
106
plot_out=new Array();
107
108
var isfirst=1;
109
var index_plot=0;
110
var step = <?=$width?> / <?=$nb_plot?> ;
111
var unit = 'bits';
112
var scale_type = '<?=$scale_type?>';
113
114
function init(evt) {
115
	SVGDoc = evt.getTarget().getOwnerDocument();
116
	SVGDoc.getElementById("switch_unit").addEventListener("mousedown", switch_unit, false);
117
	SVGDoc.getElementById("switch_scale").addEventListener("mousedown", switch_scale, false);
118
119
	go();
120
}
121
122
function switch_unit(event)
123
{
124
	SVGDoc.getElementById('switch_unit').getFirstChild().setData('Switch to ' + unit + '/s');
125
	if(unit=='bits') unit='bytes';else unit='bits';
126
}
127
128
function switch_scale(event)
129
{
130
	if(scale_type=='up') scale_type='follow';else scale_type='up';
131
	SVGDoc.getElementById('switch_scale').getFirstChild().setData('AutoScale (' + scale_type + ')');
132
}
133
134
function go() {
135
	getURL('<?=$fetch_link?>',urlcallback);
136
}
137
138
function urlcallback(obj) {
139
	var error = 0;
140
	now = new Date();
141
142
	//Show datetimelegend
143 66f8696f Scott Ullrich
	var datetime = (now.getMonth()+1) + "/" + now.getDate() + "/" + now.getFullYear() + ' ' +
144 5b237745 Scott Ullrich
		LZ(now.getHours()) + ":" + LZ(now.getMinutes()) + ":" + LZ(now.getSeconds());
145
	SVGDoc.getElementById('datetime').getFirstChild().setData(datetime);
146
147
	//shift plot to left if nb_plot is already completed
148
	var i=0;
149
	if(index_plot > <?=$nb_plot?>)
150
	{
151
		while (i <= <?=$nb_plot?>)
152
		{
153
			var a=i+1;
154
			plot_in[i]=plot_in[a];
155
			plot_out[i]=plot_out[a];
156
			i=i+1;
157
		}
158
		index_plot = <?=$nb_plot?>;
159
		plot_in[index_plot]=0;
160
		plot_out[index_plot]=0;
161
	}
162
163
	//if Geturl returns something
164
	if (obj.success){
165
		var t=obj.content.split("|");
166
		var ugmt = parseFloat(t[0]);//ugmt is an unixtimestamp style
167
		var ifin = parseInt(t[1]);//ifin must be in bytes
168
		var ifout = parseInt(t[2]);//ifout must be in bytes
169
		var scale;
170
171
		if(!isNumber(ifin) || !isNumber(ifout)) {
172
			goerror();
173
			return;
174
		} else {
175
			SVGDoc.getElementById("error").getStyle().setProperty ('visibility', 'hidden');
176
		}
177
178
		diff_ugmt  = ugmt - last_ugmt;
179
		diff_ifin  = ifin - last_ifin;
180
		diff_ifout = ifout - last_ifout;
181 66f8696f Scott Ullrich
182 5b237745 Scott Ullrich
		if (diff_ugmt == 0)
183
			diff_ugmt = 1;	/* avoid division by zero */
184
185
		last_ugmt = ugmt;
186
		last_ifin = ifin;
187
		last_ifout = ifout;
188
189
		if(isfirst) {
190
			SVGDoc.getElementById("collect_initial").getStyle().setProperty ('visibility', 'visible');
191
			setTimeout('go()',<?=1000*$first_stage_time_interval?>);
192
			isfirst=0;
193
			return;
194
		} else SVGDoc.getElementById("collect_initial").getStyle().setProperty ('visibility', 'hidden');
195
196
		plot_in[index_plot] = diff_ifin / diff_ugmt;
197
		plot_out[index_plot]= diff_ifout / diff_ugmt;
198
199
		SVGDoc.getElementById('graph_in_txt').getFirstChild().setData(formatSpeed(plot_in[index_plot],unit));
200
		SVGDoc.getElementById('graph_out_txt').getFirstChild().setData(formatSpeed(plot_out[index_plot],unit));
201
202 66f8696f Scott Ullrich
		/* determine peak for sensible scaling */
203 5b237745 Scott Ullrich
		if (scale_type == 'up') {
204
			if (plot_in[index_plot] > max)
205
				max = plot_in[index_plot];
206
			if (plot_out[index_plot] > max)
207 66f8696f Scott Ullrich
				max = plot_out[index_plot];
208 5b237745 Scott Ullrich
		} else if (scale_type == 'follow') {
209
			i = 0;
210
			max = 0;
211
			while (i <= <?=$nb_plot?>) {
212
				if (plot_in[i] > max)
213
					max = plot_in[i];
214
				if (plot_out[i] > max)
215
					max = plot_out[i];
216
				i++;
217
			}
218
		}
219
220
		var rmax;
221 66f8696f Scott Ullrich
222 5b237745 Scott Ullrich
		if (unit == 'bits') {
223
			/* round up max, such that
224
		   		100 kbps -> 200 kbps -> 400 kbps -> 800 kbps -> 1 Mbps -> 2 Mbps -> ... */
225
			rmax = 12500;
226
			i = 0;
227
			while (max > rmax) {
228
				i++;
229
				if (i && (i % 4 == 0))
230
					rmax *= 1.25;
231
				else
232
					rmax *= 2;
233
			}
234
		} else {
235
			/* round up max, such that
236
		   		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 ... */
237
			rmax = 10240;
238
			i = 0;
239
			while (max > rmax) {
240
				i++;
241
				if (i && (i % 4 == 0))
242
					rmax *= 1.25;
243
				else
244
					rmax *= 2;
245 66f8696f Scott Ullrich
246 5b237745 Scott Ullrich
				if (i == 8)
247
					rmax *= 1.024;
248
			}
249
		}
250 66f8696f Scott Ullrich
251 5b237745 Scott Ullrich
		scale = <?=$height?> / rmax;
252 66f8696f Scott Ullrich
253 5b237745 Scott Ullrich
		/* change labels accordingly */
254
		SVGDoc.getElementById('grid_txt1').getFirstChild().setData(formatSpeed(3*rmax/4,unit));
255
		SVGDoc.getElementById('grid_txt2').getFirstChild().setData(formatSpeed(2*rmax/4,unit));
256
		SVGDoc.getElementById('grid_txt3').getFirstChild().setData(formatSpeed(rmax/4,unit));
257 66f8696f Scott Ullrich
258 5b237745 Scott Ullrich
		i = 0;
259 66f8696f Scott Ullrich
260 5b237745 Scott Ullrich
		while (i <= index_plot)
261
		{
262
			var x = step * i;
263
			var y_in= <?=$height?> - (plot_in[i] * scale);
264
			var y_out= <?=$height?> - (plot_out[i] * scale);
265
			if(i==0) {
266
				var path_in = "M" + x + " " + y_in;
267
				var path_out = "M" + x + " " + y_out;
268
			}
269
			else
270
			{
271
				var path_in = path_in + " L" + x + " " + y_in;
272
				var path_out = path_out + " L" + x + " " + y_out;
273
			}
274
			i = i + 1;
275
		}
276
277
		index_plot = index_plot+1;
278
		SVGDoc.getElementById('graph_in').setAttribute("d", path_in);
279
		SVGDoc.getElementById('graph_out').setAttribute("d", path_out);
280
281
		setTimeout('go()',<?=1000*$time_interval?>);
282
	}
283
	else
284
	{ //In case of Geturl fails
285
		goerror();
286
	}
287
}
288
289
function goerror() {
290
	SVGDoc.getElementById("error").getStyle().setProperty ('visibility', 'visible');
291
	setTimeout('go()',<?=1000*$time_interval?>);
292
}
293
294
function isNumber(a) {
295
    return typeof a == 'number' && isFinite(a);
296
}
297
298
function formatSpeed(speed,unit){
299
	if(unit=='bits') return formatSpeedBits(speed);
300
	else if(unit=='bytes') return formatSpeedBytes(speed);
301
}
302
303
function formatSpeedBits(speed) {
304
	// format speed in bits/sec, input: bytes/sec
305
	if (speed <	125000)
306
		return Math.round(speed / 125) + " Kbps";
307
	else if (speed < 125000000)
308
		return Math.round(speed / 1250)/100 + " Mbps";
309
	else
310
		return Math.round(speed / 1250000)/100 + " Gbps";	/* wow! */
311
}
312
function formatSpeedBytes(speed) {
313
	// format speed in bytes/sec, input:  bytes/sec
314
	if (speed <	1048576)
315
		return Math.round(speed / 10.24)/100 + " KB/s";
316
	else if (speed < 1073741824)
317
		return Math.round(speed / 10485.76)/100 + " MB/s";
318
	else
319
		return Math.round(speed / 10737418.24)/100 + " GB/s";	/* wow! */
320
}
321
function LZ(x) {
322
	return (x < 0 || x > 9 ? "" : "0") + x
323
}
324
]]></script>
325
</svg>