Project

General

Profile

Download (12.2 KB) Statistics
| Branch: | Tag: | Revision:
1
#!/usr/local/bin/php -f
2
<?php
3
/* $Id$ */
4
/*
5
	graph.php
6
	Copyright (C) 2004 Scott Ullrich
7
	originally part of m0n0wall (http://m0n0.ch/wall)
8
	Copyright (C) 2004 T. Lechat <dev@lechat.org> and Manuel Kasper <mk@neon1.net>.
9
	All rights reserved.
10

    
11
	Redistribution and use in source and binary forms, with or without
12
	modification, are permitted provided that the following conditions are met:
13

    
14
	1. Redistributions of source code must retain the above copyright notice,
15
	   this list of conditions and the following disclaimer.
16

    
17
	2. Redistributions in binary form must reproduce the above copyright
18
	   notice, this list of conditions and the following disclaimer in the
19
	   documentation and/or other materials provided with the distribution.
20

    
21
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
	POSSIBILITY OF SUCH DAMAGE.
31
*/
32

    
33
// VERSION 1.0.4
34

    
35
/********** HTTP GET Based Conf ***********/
36
$ifnum=@$_GET["ifnum"];							//BSD / SNMP interface name / number
37
$ifname=@$_GET["ifname"]?$_GET["ifname"]:"Interface $ifnum";		//Interface name that will be showed on top right of graph
38

    
39
/********* Other conf *******/
40
$scale_type="up";		//Autoscale default setup : "up" = only increase scale; "follow" = increase and decrease scale according to current graphed datas
41
$nb_plot=120;			//NB plot in graph
42
$time_interval=1;		//Refresh time Interval
43
$first_stage_time_interval=2;	//First stage time Intervall
44

    
45
$urldata=@$_SERVER["SCRIPT_NAME"];
46
$fetch_link = "ifstats.cgi?$ifnum";
47

    
48
//Style
49
$style['bg']="fill:white;stroke:none;stroke-width:0;opacity:1;";
50
$style['axis']="fill:black;stroke:black;stroke-width:1;";
51
$style['in']="fill:#CC0000; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:7;";
52
$style['out']="fill:#000000; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:7;";
53
$style['graph_in']="fill:none;stroke:#CC0000;stroke-width:1;opacity:0.8;";
54
$style['graph_out']="fill:none;stroke:#000000;stroke-width:1;opacity:0.8;";
55
$style['legend']="fill:black; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4;";
56
$style['graphname']="fill:#CC0000; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:8;";
57
$style['grid_txt']="fill:gray; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:6;";
58
$style['grid']="stroke:gray;stroke-width:1;opacity:0.5;";
59
$style['switch_unit']="fill:#CC0000; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4; text-decoration:underline;";
60
$style['switch_scale']="fill:#CC0000; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4; text-decoration:underline;";
61
$style['error']="fill:blue; font-family:Arial; font-size:4;";
62
$style['collect_initial']="fill:gray; font-family:Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size:4;";
63

    
64
//Error text if we cannot fetch data : depends on which method is used
65
$error_text = "Cannot get data about interface $ifnum";
66

    
67
$height=100;		//SVG internal height : do not modify
68
$width=200;		//SVG internal width : do not modify
69

    
70
/********* Graph DATA **************/
71
header("Content-type: image/svg+xml");
72
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)">
73
<g id="graph" style="visibility:visible">
74
	<rect id="bg" x1="0" y1="0" x2="<?=$width?>" y2="<?=$height?>" style="<?=$style['bg']?>"/>
75
	<line id="axis_x" x1="0" y1="0" x2="0" y2="<?=$height?>" style="<?=$style['axis']?>"/>
76
	<line id="axis_y" x1="0" y1="<?=$height?>" x2="<?=$width?>" y2="<?=$height?>" style="<?=$style['axis']?>"/>
77
	<path id="graph_out" d="M0 <?=$height?> L 0 <?=$height?>" style="<?=$style['graph_out']?>"/>
78
	<path id="graph_in"  d="M0 <?=$height?> L 0 <?=$height?>" style="<?=$style['graph_in']?>"/>
79
	<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]?>"/>
80
	<text id="grid_txt1" x="<?=$width?>" y="<?=$height/4*1?>" style="<?=$style['grid_txt']?> text-anchor:end"> </text>
81
	<text id="grid_txt2" x="<?=$width?>" y="<?=$height/4*2?>" style="<?=$style['grid_txt']?> text-anchor:end"> </text>
82
	<text id="grid_txt3" x="<?=$width?>" y="<?=$height/4*3?>" style="<?=$style['grid_txt']?> text-anchor:end"> </text>
83
	<text id="graph_in_lbl" x="5" y="8" style="<?=$style['in']?>">In</text>
84
	<text id="graph_out_lbl" x="5" y="16" style="<?=$style['out']?> ">Out</text>
85
	<text id="graph_in_txt" x="20" y="8" style="<?=$style['in']?>"> </text>
86
	<text id="graph_out_txt" x="20" y="16" style="<?=$style['out']?> "> </text>
87
	<text id="ifname" x="<?=$width?>" y="8" style="<?=$style['graphname']?> text-anchor:end"><?=$ifname?></text>
88
	<text id="switch_unit" x="<?=$width*0.55?>" y="5" style="<?=$style['switch_unit']?>">Switch to bytes/s</text>
89
	<text id="switch_scale" x="<?=$width*0.55?>" y="11" style="<?=$style['switch_scale']?>">AutoScale (<?=$scale_type?>)</text>
90
	<text id="datetime" x="<?=$width*0.33?>" y="5" style="<?=$style['legend']?>"> </text>
91
	<text id="graphlast" x="<?=$width*0.55?>" y="17" style="<?=$style['legend']?>">Graph shows last <?=$time_interval*$nb_plot?> seconds</text>
92
	<polygon id="axis_arrow_x" style="<?=$style['axis']?>" points="<?=($width) . "," . ($height)?> <?=($width-2) . "," . ($height-2)?> <?=($width-2) . "," . $height?>"/>
93
	<text id="error" x="<?=$width*0.5?>" y="<?=$height*0.5?>"  style="visibility:hidden;<?=$style['error']?> text-anchor:middle"><?=$error_text?></text>
94
	<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>
95
</g>
96

    
97
<script type="text/ecmascript"><![CDATA[
98
var SVGDoc;
99
var last_ifin=0;
100
var last_ifout=0;
101
var last_ugmt=0;
102
var diff_ugmt=0;
103
var diff_ifin=0;
104
var diff_ifout=0;
105
var max = 0;
106
plot_in=new Array();
107
plot_out=new Array();
108

    
109
var isfirst=1;
110
var index_plot=0;
111
var step = <?=$width?> / <?=$nb_plot?> ;
112
var unit = 'bits';
113
var scale_type = '<?=$scale_type?>';
114

    
115
function init(evt) {
116
	SVGDoc = evt.getTarget().getOwnerDocument();
117
	SVGDoc.getElementById("switch_unit").addEventListener("mousedown", switch_unit, false);
118
	SVGDoc.getElementById("switch_scale").addEventListener("mousedown", switch_scale, false);
119

    
120
	go();
121
}
122

    
123
function switch_unit(event)
124
{
125
	SVGDoc.getElementById('switch_unit').getFirstChild().setData('Switch to ' + unit + '/s');
126
	if(unit=='bits') unit='bytes';else unit='bits';
127
}
128

    
129
function switch_scale(event)
130
{
131
	if(scale_type=='up') scale_type='follow';else scale_type='up';
132
	SVGDoc.getElementById('switch_scale').getFirstChild().setData('AutoScale (' + scale_type + ')');
133
}
134

    
135
function go() {
136
	getURL('<?=$fetch_link?>',urlcallback);
137
}
138

    
139
function urlcallback(obj) {
140
	var error = 0;
141
	now = new Date();
142

    
143
	//Show datetimelegend
144
	var datetime = (now.getMonth()+1) + "/" + now.getDate() + "/" + now.getFullYear() + ' ' +
145
		LZ(now.getHours()) + ":" + LZ(now.getMinutes()) + ":" + LZ(now.getSeconds());
146
	SVGDoc.getElementById('datetime').getFirstChild().setData(datetime);
147

    
148
	//shift plot to left if nb_plot is already completed
149
	var i=0;
150
	if(index_plot > <?=$nb_plot?>)
151
	{
152
		while (i <= <?=$nb_plot?>)
153
		{
154
			var a=i+1;
155
			plot_in[i]=plot_in[a];
156
			plot_out[i]=plot_out[a];
157
			i=i+1;
158
		}
159
		index_plot = <?=$nb_plot?>;
160
		plot_in[index_plot]=0;
161
		plot_out[index_plot]=0;
162
	}
163

    
164
	//if Geturl returns something
165
	if (obj.success){
166
		var t=obj.content.split("|");
167
		var ugmt = parseFloat(t[0]);//ugmt is an unixtimestamp style
168
		var ifin = parseInt(t[1]);//ifin must be in bytes
169
		var ifout = parseInt(t[2]);//ifout must be in bytes
170
		var scale;
171

    
172
		if(!isNumber(ifin) || !isNumber(ifout)) {
173
			goerror();
174
			return;
175
		} else {
176
			SVGDoc.getElementById("error").getStyle().setProperty ('visibility', 'hidden');
177
		}
178

    
179
		diff_ugmt  = ugmt - last_ugmt;
180
		diff_ifin  = ifin - last_ifin;
181
		diff_ifout = ifout - last_ifout;
182

    
183
		if (diff_ugmt == 0)
184
			diff_ugmt = 1;	/* avoid division by zero */
185

    
186
		last_ugmt = ugmt;
187
		last_ifin = ifin;
188
		last_ifout = ifout;
189

    
190
		if(isfirst) {
191
			SVGDoc.getElementById("collect_initial").getStyle().setProperty ('visibility', 'visible');
192
			setTimeout('go()',<?=1000*$first_stage_time_interval?>);
193
			isfirst=0;
194
			return;
195
		} else SVGDoc.getElementById("collect_initial").getStyle().setProperty ('visibility', 'hidden');
196

    
197
		plot_in[index_plot] = diff_ifin / diff_ugmt;
198
		plot_out[index_plot]= diff_ifout / diff_ugmt;
199

    
200
		SVGDoc.getElementById('graph_in_txt').getFirstChild().setData(formatSpeed(plot_in[index_plot],unit));
201
		SVGDoc.getElementById('graph_out_txt').getFirstChild().setData(formatSpeed(plot_out[index_plot],unit));
202

    
203
		/* determine peak for sensible scaling */
204
		if (scale_type == 'up') {
205
			if (plot_in[index_plot] > max)
206
				max = plot_in[index_plot];
207
			if (plot_out[index_plot] > max)
208
				max = plot_out[index_plot];
209
		} else if (scale_type == 'follow') {
210
			i = 0;
211
			max = 0;
212
			while (i <= <?=$nb_plot?>) {
213
				if (plot_in[i] > max)
214
					max = plot_in[i];
215
				if (plot_out[i] > max)
216
					max = plot_out[i];
217
				i++;
218
			}
219
		}
220

    
221
		var rmax;
222

    
223
		if (unit == 'bits') {
224
			/* round up max, such that
225
		   		100 kbps -> 200 kbps -> 400 kbps -> 800 kbps -> 1 Mbps -> 2 Mbps -> ... */
226
			rmax = 12500;
227
			i = 0;
228
			while (max > rmax) {
229
				i++;
230
				if (i && (i % 4 == 0))
231
					rmax *= 1.25;
232
				else
233
					rmax *= 2;
234
			}
235
		} else {
236
			/* round up max, such that
237
		   		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 ... */
238
			rmax = 10240;
239
			i = 0;
240
			while (max > rmax) {
241
				i++;
242
				if (i && (i % 4 == 0))
243
					rmax *= 1.25;
244
				else
245
					rmax *= 2;
246

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

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

    
254
		/* change labels accordingly */
255
		SVGDoc.getElementById('grid_txt1').getFirstChild().setData(formatSpeed(3*rmax/4,unit));
256
		SVGDoc.getElementById('grid_txt2').getFirstChild().setData(formatSpeed(2*rmax/4,unit));
257
		SVGDoc.getElementById('grid_txt3').getFirstChild().setData(formatSpeed(rmax/4,unit));
258

    
259
		i = 0;
260

    
261
		while (i <= index_plot)
262
		{
263
			var x = step * i;
264
			var y_in= <?=$height?> - (plot_in[i] * scale);
265
			var y_out= <?=$height?> - (plot_out[i] * scale);
266
			if(i==0) {
267
				var path_in = "M" + x + " " + y_in;
268
				var path_out = "M" + x + " " + y_out;
269
			}
270
			else
271
			{
272
				var path_in = path_in + " L" + x + " " + y_in;
273
				var path_out = path_out + " L" + x + " " + y_out;
274
			}
275
			i = i + 1;
276
		}
277

    
278
		index_plot = index_plot+1;
279
		SVGDoc.getElementById('graph_in').setAttribute("d", path_in);
280
		SVGDoc.getElementById('graph_out').setAttribute("d", path_out);
281

    
282
		setTimeout('go()',<?=1000*$time_interval?>);
283
	}
284
	else
285
	{ //In case of Geturl fails
286
		goerror();
287
	}
288
}
289

    
290
function goerror() {
291
	SVGDoc.getElementById("error").getStyle().setProperty ('visibility', 'visible');
292
	setTimeout('go()',<?=1000*$time_interval?>);
293
}
294

    
295
function isNumber(a) {
296
    return typeof a == 'number' && isFinite(a);
297
}
298

    
299
function formatSpeed(speed,unit){
300
	if(unit=='bits') return formatSpeedBits(speed);
301
	else if(unit=='bytes') return formatSpeedBytes(speed);
302
}
303

    
304
function formatSpeedBits(speed) {
305
	// format speed in bits/sec, input: bytes/sec
306
	if (speed <	125000)
307
		return Math.round(speed / 125) + " Kbps";
308
	else if (speed < 125000000)
309
		return Math.round(speed / 1250)/100 + " Mbps";
310
	else
311
		return Math.round(speed / 1250000)/100 + " Gbps";	/* wow! */
312
}
313
function formatSpeedBytes(speed) {
314
	// format speed in bytes/sec, input:  bytes/sec
315
	if (speed <	1048576)
316
		return Math.round(speed / 10.24)/100 + " KB/s";
317
	else if (speed < 1073741824)
318
		return Math.round(speed / 10485.76)/100 + " MB/s";
319
	else
320
		return Math.round(speed / 10737418.24)/100 + " GB/s";	/* wow! */
321
}
322
function LZ(x) {
323
	return (x < 0 || x > 9 ? "" : "0") + x
324
}
325
]]></script>
326
</svg>
(39-39/112)