Project

General

Profile

Download (7.91 KB) Statistics
| Branch: | Tag: | Revision:
1
/*
2
 * part of pfSense (https://www.pfsense.org)
3
 * Copyright (c) 2016 Rubicon Communications, LLC (Netgate)
4
 * All rights reserved.
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18

    
19
function graph_init() {
20

    
21
	window.charts = {};
22
    window.myData = {};
23
    window.updateIds = 0;
24
    window.updateTimerIds = 0;
25
    window.latest = [];
26
    //TODO make it fall on a second value so it increments better
27
    var now = then = new Date(Date.now());
28

    
29
    var nowTime = now.getTime();
30

    
31
	$.each(window.interfaces, function( key, value ) {
32

    
33
		myData[value] = [];
34
		updateIds = 0;
35
		updateTimerIds = 0;
36

    
37
		var itemIn = new Object();
38
		var itemOut = new Object();
39

    
40
		itemIn.key = value + " (in)";
41
		if (window.invert) {
42
			itemIn.area = true;
43
		}
44
		itemIn.first = true;
45
		itemIn.values = [{x: nowTime, y: 0}];
46
		myData[value].push(itemIn);
47

    
48
		itemOut.key = value + " (out)";
49
		if (window.invert) {
50
			itemOut.area = true;
51
		}
52
		itemOut.first = true;
53
		itemOut.values = [{x: nowTime, y: 0}];
54
		myData[value].push(itemOut);
55

    
56
	});
57

    
58
	if (window.interfaces.length > 0) {
59
		draw_graph(then);
60
	}
61
}
62

    
63
function graph_visibilitycheck() {
64
	//re-draw graph when the page goes from inactive (in it's window) to active
65
	Visibility.change(function (e, state) {
66
		if (window.graph_backgroundupdate) {
67
			return;
68
		}
69
		if (state === "visible") {
70

    
71
			now = then = new Date(Date.now());
72

    
73
			var nowTime = now.getTime();
74

    
75
			$.each(window.interfaces, function( key, value ) {
76

    
77
				Visibility.stop(updateIds);
78
				clearInterval(updateTimerIds);
79

    
80
				myData[value] = [];
81

    
82
				var itemIn = new Object();
83
				var itemOut = new Object();
84

    
85
				itemIn.key = value + " (in)";
86
				if (window.invert) {
87
					itemIn.area = true;
88
				}
89
				itemIn.first = true;
90
				itemIn.values = [{x: nowTime, y: 0}];
91
				myData[value].push(itemIn);
92

    
93
				itemOut.key = value + " (out)";
94
				if (window.invert) {
95
					itemOut.area = true;
96
				}
97
				itemOut.first = true;
98
				itemOut.values = [{x: nowTime, y: 0}];
99
				myData[value].push(itemOut);
100

    
101
			});
102

    
103
			if (window.interfaces.length > 0) {
104
				draw_graph(then);
105
			}
106

    
107
		}
108
	});
109
}
110

    
111
function draw_graph(then) {
112

    
113
	d3.select("div[id^=nvtooltip-]").remove();
114
	d3.select(".interface-label").remove();
115

    
116
	var invert = window.invert;
117
	var size = window.size;
118
	var refreshInterval = window.interval;
119
	var lasttime = 0;
120
	startTime = 120 * refreshInterval;
121
	then.setSeconds(then.getSeconds() - startTime);
122
	var thenTime = then.getTime();
123
	var refreshGraphFunction_running = false;
124

    
125
	$.each( window.interfaces, function( key, value ) {
126
		myData[value]['interfacename'] = graph_interfacenames[value];
127
		latest[value + 'in'] = 0;
128
		latest[value + 'out'] = 0;
129

    
130
		var stepTime = thenTime;
131

    
132
		//initialize first 120 graph points to zero
133
		for (i = 1; i < 120; i++) {
134

    
135
			stepTime = stepTime + (1000 * refreshInterval);
136

    
137
			myData[value].forEach(function(entry) {
138
				entry.values.push({
139
					x: stepTime,
140
					y: 0
141
				});
142
			});
143

    
144
		}
145

    
146
		nv.addGraph(function() {
147

    
148
			charts[value] = nv.models.lineChart()
149
						.useInteractiveGuideline(true)
150
						.color(d3.scale.category20().range())
151
						.rightAlignYAxis(true)
152
						.margin({top: 0, left:25, bottom: 30, right: 45});
153

    
154
			charts[value]
155
				.x(function(d,i) { return d.x });
156

    
157
			charts[value].xAxis
158
				.tickFormat(function (d) {
159
					return d3.time.format('%M:%S')(new Date(d));
160
				});
161

    
162
			var sizeLabel = $( "#traffic-graph-size option:selected" ).text();
163

    
164
			d3.select('#traffic-chart-' + value + ' svg')
165
				.append("text")
166
				.attr('class', 'interface-label')
167
				.attr("x", 20)             
168
				.attr("y", 20)
169
				.attr("font-size", 18)
170
				.text(myData[value]['interfacename']);
171

    
172
			charts[value].yAxis
173
		    	.tickFormat(d3.format('.2s'))
174
		    	.showMaxMin(false);
175

    
176
			d3.select('#traffic-chart-' + value + ' svg')
177
				.datum(myData[value])
178
		    	.transition().duration(500)
179
		    	.call(charts[value]);
180

    
181
			nv.utils.windowResize(charts[value].update);
182

    
183
			//custom tooltip contents
184
			charts[value].interactiveLayer.tooltip.contentGenerator(function(data) {
185

    
186
				var units = 'b/s';
187
				if(window.size === 1) {
188
					units = 'B/s'
189
				}
190

    
191
				var content = '<h3>' + d3.time.format('%Y-%m-%d %H:%M:%S')(new Date(data.value)) + '</h3><table><tbody>';
192

    
193
				for ( var v = 0; v < data.series.length; v++ ){
194

    
195
					var rawValue = data.series[v].value;
196

    
197
					if(invert && data.series[v].key.includes("(out)")) {
198
						rawValue = 0 - rawValue;
199
					}
200

    
201
					var sValue = d3.formatPrefix(rawValue);
202

    
203
					//TODO change unit based on unit size
204
					var formattedVal = sValue.scale(rawValue).toFixed(2) + ' ' + sValue.symbol + units;
205

    
206
					content += '<tr><td class="legend-color-guide"><div style="background-color: ' + data.series[v].color + '"></div></td><td>' + data.series[v].key + '</td><td class="value"><strong>' + formattedVal + '</strong></td></tr>';
207

    
208
				}
209

    
210
				content += '</tbody></table>';
211

    
212
				return content;
213

    
214
			});
215

    
216
			return charts[value];
217
		});
218

    
219
	});
220

    
221
	var refreshGraphFunction = function(){
222
		if (refreshGraphFunction_running) {
223
			return;
224
		}
225
		refreshGraphFunction_running = true;
226
		d3.json("ifstats.php")
227
		.header("Content-Type", "application/x-www-form-urlencoded")
228
		.post('if='+window.interfaces.join('|')+'&realif='+window.realinterfaces.join('|'), function(error, json) { //TODO all ifs again
229

    
230
			if (error) {
231

    
232
				Visibility.stop(updateIds);
233
				clearInterval(updateTimerIds);
234
				$(".traffic-widget-chart").remove();
235
				$("#traffic-chart-error").show().html('<strong>Error</strong>: ' + error);
236
				return console.warn(error);
237

    
238
			}
239

    
240
			if (json.error) {
241

    
242
				Visibility.stop(updateIds);
243
				clearInterval(updateTimerIds);
244
				$(".traffic-widget-chart").remove();
245
				$("#traffic-chart-error").show().html('<strong>Error</strong>: ' + json.error);
246
				return console.warn(json.error);
247

    
248
			}
249

    
250
			var setTime = true;
251
			var xtime = 0;
252
			var timeDiff = 0;
253
			$.each(json, function( key, ifVals ) {
254
				if (setTime == true) {
255
					var valueTime = ifVals[0].values[0];
256
					timeDiff = valueTime - lasttime;
257
					lasttime = valueTime;
258
					xtime = valueTime * 1000;
259
					setTime = false;
260
				}
261
				label = $('#traffic-chart-' + key + ' svg > .interface-label');
262
				$(label).text(ifVals.name);
263
				if(!myData[key][0].first) {
264
					var trafficIn = ((ifVals[0].values[1] * size) - latest[ifVals[0].key]) / timeDiff;
265
					var trafficOut = ((ifVals[1].values[1] * size) - latest[ifVals[1].key]) / timeDiff;
266

    
267
					if(window.invert) {
268
						trafficOut = 0 - trafficOut;
269
					}
270

    
271
					myData[key][0].values.push({
272
						x: xtime,
273
						y: trafficIn
274
					});
275

    
276
					myData[key][1].values.push({
277
						x: xtime,
278
						y: trafficOut
279
					});
280

    
281
				} else {
282
					myData[key][0].values.push({
283
						x: xtime,
284
						y: 0
285
					});
286

    
287
					myData[key][1].values.push({
288
						x: xtime,
289
						y: 0
290
					});
291
				}
292

    
293
				latest[ifVals[0].key] = ifVals[0].values[1] * size;
294
				latest[ifVals[1].key] = ifVals[1].values[1] * size;
295

    
296
				myData[key][0].first = false;
297
				myData[key][1].first = false;
298

    
299
				myData[key][0].values.shift();
300
				myData[key][1].values.shift();
301

    
302
				if (!Visibility.hidden()) {
303
					/*
304
					 * don't draw graph when tab is not
305
					 * visible. This also prevents lots of
306
					 * timers stacking up waiting for a
307
					 * frame update.
308
					 */
309
					charts[key].update();
310
				}
311

    
312
			});
313

    
314
			refreshGraphFunction_running = false;
315
		});
316

    
317
	}
318
	
319
	if(window.graph_backgroundupdate) {
320
		updateTimerIds = setInterval(refreshGraphFunction, refreshInterval * 1000);
321
	} else {
322
		//only update the graphs when tab is active in window to save resources and prevent build up
323
		updateIds = Visibility.every(refreshInterval * 1000, refreshGraphFunction);
324
	}
325
}
(4-4/4)