Project

General

Profile

Download (12.2 KB) Statistics
| Branch: | Tag: | Revision:
1
#!/usr/local/bin/php -f
2
<?php
3
/*
4
	graph.php
5
	Copyright (C) 2004 Scott Ullrich
6
	originally part of m0n0wall (http://m0n0.ch/wall)
7
	Copyright (C) 2004 T. Lechat <dev@lechat.org> and Manuel Kasper <mk@neon1.net>.
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
// 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
$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
$style['legend']="fill:black; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4;";
55
$style['graphname']="fill:#CC0000; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:8;";
56
$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
$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
$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
	var datetime = (now.getMonth()+1) + "/" + now.getDate() + "/" + now.getFullYear() + ' ' +
144
		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

    
182
		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
		/* determine peak for sensible scaling */
203
		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
				max = plot_out[index_plot];
208
		} 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

    
222
		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

    
246
				if (i == 8)
247
					rmax *= 1.024;
248
			}
249
		}
250

    
251
		scale = <?=$height?> / rmax;
252

    
253
		/* 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

    
258
		i = 0;
259

    
260
		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>
(36-36/100)