rewrote javascript for full async operation, added support for different chart type per graph, smart updating only the charts on screen
Costa Tsaousis (ktsaou) committed
Apr 1, 2014 at 02:05 UTC
405713ee737abbf42b6e23b1c65719c08adef231
4 files changed
+374
-268
netdata.c
+6
-6
@@ -2159,11 +2159,11 @@ int do_proc_net_netstat() {
2159
if(r == EOF) break;
2160
if(r != 12) error("Cannot read /proc/net/netstat IpExt line. Expected 12 params, read %d.", r);
2161
2162
- RRD_STATS *st = rrd_stats_find(RRD_TYPE_NET ".ipv4");
2162
+ RRD_STATS *st = rrd_stats_find(RRD_TYPE_NET_SNMP ".net");
2163
if(!st) {
2164
- st = rrd_stats_create(RRD_TYPE_NET ".ipv4", RRD_TYPE_NET ".ipv4", save_history, "All IPv4 Bandwidth", "bandwidth in kilobits/s", RRD_TYPE_NET);
2164
+ st = rrd_stats_create(RRD_TYPE_NET_SNMP ".net", RRD_TYPE_NET_SNMP ".net", save_history, "All IPv4 Bandwidth", "bandwidth in kilobits/s", RRD_TYPE_NET_SNMP);
2165
if(!st) {
2166
- error("Cannot create RRD_STATS for %s.", RRD_TYPE_NET ".ipv4");
2166
+ error("Cannot create RRD_STATS for %s.", RRD_TYPE_NET_SNMP ".net");
2167
continue;
2168
}
2169
@@ -2376,11 +2376,11 @@ int do_proc_net_ip_vs_stats() {
2376
rrd_stats_dimension_set(st, "sent", &OutPackets);
2377
rrd_stats_done(st);
2378
2379
- st = rrd_stats_find(RRD_TYPE_NET ".ipvs");
2379
+ st = rrd_stats_find(RRD_TYPE_NET_IPVS ".net");
2380
if(!st) {
2381
- st = rrd_stats_create(RRD_TYPE_NET ".ipvs", RRD_TYPE_NET ".ipvs", save_history, "IPVS Bandwidth", "bandwidth in kilobits/s", RRD_TYPE_NET);
2381
+ st = rrd_stats_create(RRD_TYPE_NET_IPVS ".net", RRD_TYPE_NET_IPVS ".net", save_history, "IPVS Bandwidth", "bandwidth in kilobits/s", RRD_TYPE_NET_IPVS);
2382
if(!st) {
2383
- error("Cannot create RRD_STATS for %s.", RRD_TYPE_NET ".ipvs");
2383
+ error("Cannot create RRD_STATS for %s.", RRD_TYPE_NET_IPVS ".net");
2384
return 1;
2385
}
2386
web/index.html
+197
-171
@@ -22,23 +22,34 @@
22
23
<!-- NetData -->
24
<script type="text/javascript" src="/file/netdata.js"></script>
25
+ <script type="text/javascript" src="/file/jquery.visible.js"></script>
26
<script type="text/javascript">
27
28
// Set a callback to run when the Google Visualization API is loaded.
28
- google.setOnLoadCallback(drawCharts);
29
+ google.setOnLoadCallback(initCharts);
30
31
+ var MODE_THUMBS = 1;
32
+ var MODE_MAIN = 2;
33
+ var mode; // one of the MODE_* values
34
+
35
var mycharts = new Array();
36
var mainchart;
37
38
+ function chartIsLoadingHTML(width, height) { return "<table><tr><td align=\"center\" width=\"" + width + "\" height=\"" + height + "\"><h4><span class=\"glyphicon glyphicon-refresh\"></span><br/><br/>loading chart<br/><br/><span class=\"label label-default\">Please wait...</span></h4></td></tr></table>"; }
39
+
40
+ function showChartIsLoading(id, width, height) { document.getElementById(id).innerHTML = chartIsLoadingHTML(width, height); }
41
+
42
+ // copy the chart c to mainchart
43
+ // switch to main graphs screen
44
function mainChart(c) {
45
if(mainchart && mainchart.chart) mainchart.chart.clearChart();
46
47
mainchart = $.extend(true, {}, c);
48
49
mainchart.chart = null;
39
- mainchart.width = Math.round(((window.innerWidth * 0.95) - 50) / 1);
40
- mainchart.height = window.innerHeight - 200;
41
- if(mainchart.height < 300) mainchart.height = 300;
50
+ mainchart.chartOptions.width = Math.round((($(window).width() * 0.95) - 50) / 1);
51
+ mainchart.chartOptions.height = $(window).height() - 200;
52
+ if(mainchart.chartOptions.height < 300) mainchart.chartOptions.height = 300;
53
54
mainchart.thumbnail = false;
55
mainchart.group = 5;
@@ -65,9 +76,11 @@
76
// show max 10 mins of data
77
if(mainchart.points_to_show * mainchart.group > 1200) mainchart.points_to_show = 1200 / mainchart.group;
78
79
+ // initialize the div
80
+ showChartIsLoading(mainchart.div, mainchart.chartOptions.width, mainchart.chartOptions.height);
81
+
82
document.getElementById('maingraph_title').innerHTML = " <b> " + mainchart.title + " </b> (as " + mainchart.group_method + " of every " + (mainchart.group * mainchart.update_every) + " seconds)";
83
70
- refreshChart(mainchart);
84
showMainGraph();
85
}
86
@@ -75,201 +88,206 @@
88
mainChart(mycharts[i]);
89
}
90
91
+ // refresh the main chart
92
+ // make sure it gets updated frequently
93
+ function mainChartRefresh() {
94
+ if(!mainchart || mode != MODE_MAIN) {
95
+ if(mainchart) mainchart.clearChart();
96
+ showThumbGraphs();
97
+ return;
98
+ }
99
+
100
+ var now = new Date().getTime();
101
+
102
+ if((now - mainchart.last_updated) >= mainchart.chart_update_every) {
103
+ refreshChart(mainchart, triggerMainChartRefresh);
104
+ mainchart.last_updated = now;
105
+ }
106
+ else triggerMainChartRefresh();
107
+ }
108
+
109
+ // callback for refreshing the main chart
110
+ function triggerMainChartRefresh() {
111
+ if(mode == MODE_MAIN) setTimeout(mainChartRefresh, 500);
112
+ }
113
+
114
+ // calculate the proper width for the thumb charts
115
function thumbWidth() {
79
- var items = Math.round(((window.innerWidth * 0.95) - 50) / 500);
116
+ var items = Math.round((($(window).width() * 0.95) - 50) / 500);
117
if(items < 1) items = 1;
118
82
- var width = Math.round(((window.innerWidth * 0.95) - 50) / items) - 1;
83
- console.log("window = " + ((window.innerWidth * 0.95) - 50) + ", items = " + items + ", width = " + width);
119
+ var width = Math.round((($(window).width() * 0.95) - 50) / items) - 1;
120
+ //console.log("window = " + (($(window).width() * 0.95) - 50) + ", items = " + items + ", width = " + width);
121
122
return width;
123
}
124
125
+ // resize all charts
126
+ // if the thumb charts need resize in their width, reset them
127
function resizeCharts() {
128
+ var width = Math.round((($(window).width() * 0.95) - 50) / 1);
129
if(mainchart) {
90
- mainchart.width = Math.round(((window.innerWidth * 0.95) - 50) / 1);
91
- mainchart.height = window.innerHeight - 200;
130
+ mainchart.chartOptions.width = Math.round((($(window).width() * 0.95) - 50) / 1);
131
+ mainchart.chartOptions.height = $(window).height() - 200;
132
+ mainchart.last_updated = 0;
133
}
134
94
- var width = thumbWidth();
135
+ width = thumbWidth();
136
$.each(mycharts, function(i, c) {
96
- if(c.enabled) {
97
- c.width = width;
98
- c.needs_refresh = true;
137
+ if(c.enabled && c.chartOptions.width != width) {
138
+ if(c.chart) c.chart.clearChart();
139
+ c.chart = null;
140
+ c.chartOptions.width = width;
141
+ showChartIsLoading(c.div, c.chartOptions.width, c.chartOptions.height);
142
+ c.last_updated = 0;
143
}
144
});
145
}
146
103
- var go_thumbs = 0;
104
- var go_main = 0;
105
- function drawCharts() {
106
- myChartsRefreshInternal(mycharts.length);
107
- };
108
-
147
// load the charts from the server
148
// generate html for the thumbgraphs to support them
149
function initCharts() {
150
var width = thumbWidth();
151
var height = 200;
152
115
- mycharts = loadCharts();
116
- if(mycharts == null || mycharts.length == 0) {
117
- alert("Cannot load data from server.");
118
- return;
119
- }
120
-
121
- var scroll = document.getElementById("graphs");
122
- if(!scroll) {
123
- alert("Cannot find the scroller");
124
- return;
125
- }
126
-
127
- function chartssort(a, b) {
128
- if(a.userpriority < b.userpriority) return -1;
129
- return 1;
130
- }
131
- mycharts.sort(chartssort);
132
-
133
- document.getElementById('hostname_id').innerHTML = mycharts[0].hostname;
134
- document.title = mycharts[0].hostname;
153
+ loadCharts(function(c) {
154
+ mycharts = c;
155
136
- // create an array for grouping all same-type graphs together
137
- var categories = new Array();
138
- $.each(mycharts, function(i, c) {
139
- c.thumbnail = false;
140
- c.last_updated = 0;
141
- c.width = width;
142
- c.height = height;
143
- c.enabled = true;
144
- c.needs_refresh = true;
145
-
146
- if(c.userpriority == "IGNORE") c.enabled = false;
147
- if(c.usertitle) c.title = c.usertitle;
148
-
149
- if(c.type == "tc") {
150
- c.category = "Quality of Service"
151
- c.glyphicon = "glyphicon-transfer";
152
- c.group = 30;
153
- c.group_method = "average";
154
- }
155
- else if(c.type == "net") {
156
- c.category = "Network Traffic"
157
- c.glyphicon = "glyphicon-cloud";
158
- c.group = 10;
159
- c.group_method = "max";
160
-
161
- if((c.id.substring(c.id.length - 4, c.id.length) == "-ifb") ||
162
- c.id == "net.lo")
163
- c.enabled = false;
164
- }
165
- else if(c.type == "ipv4") {
166
- c.category = "IPv4 connections"
167
- c.glyphicon = "glyphicon-resize-full";
168
- c.group = 30;
169
- c.group_method = "max";
156
+ if(mycharts == null || mycharts.length == 0) {
157
+ alert("Cannot load data from server.");
158
+ return;
159
}
171
- else if(c.type == "conntrack") {
172
- c.category = "Netfilter Connections Tracked"
173
- c.glyphicon = "glyphicon-eye-open";
174
- c.group = 30;
175
- c.group_method = "max";
176
- }
177
- else if(c.type == "ipvs") {
178
- c.category = "IPVS"
179
- c.glyphicon = "glyphicon-sort";
180
- c.group = 30;
181
- c.group_method = "max";
182
- }
183
- else if(c.type == "disk") {
184
- c.category = "Disk I/O"
185
- c.glyphicon = "glyphicon-floppy-disk";
186
- c.group = 20;
187
- c.group_method = "max";
160
+
161
+ var thumbsContainer = document.getElementById("graphs");
162
+ if(!thumbsContainer) {
163
+ alert("Cannot find the thumbsContainer");
164
+ return;
165
}
189
- else {
190
- c.category = "Unknown"
191
- c.glyphicon = "glyphicon-search";
192
- c.group = 60;
193
- c.group_method = "max";
166
+
167
+ function chartssort(a, b) {
168
+ if(a.userpriority < b.userpriority) return -1;
169
+ return 1;
170
}
171
+ mycharts.sort(chartssort);
172
+
173
+ document.getElementById('hostname_id').innerHTML = mycharts[0].hostname;
174
+ document.title = mycharts[0].hostname;
175
+
176
+ // create an array for grouping all same-type graphs together
177
+ var categories = new Array();
178
+ $.each(mycharts, function(i, c) {
179
+ c.last_updated = 0;
180
+ c.chartOptions.width = width;
181
+ c.chartOptions.height = height;
182
+
183
+ switch(c.type) {
184
+ case "tc":
185
+ c.glyphicon = "glyphicon-transfer";
186
+ c.group = 30;
187
+ c.group_method = "average";
188
+ break;
189
196
- // calculate the time to refresh each chart
197
- c.chart_update_every = c.group * 1000; // milliseconds
190
+ case "net":
191
+ c.glyphicon = "glyphicon-cloud";
192
+ c.group = 10;
193
+ c.group_method = "max";
194
+ break;
195
199
- // calculate how many point to show for each chart
200
- c.points_to_show = Math.round(c.entries / c.group) - 1;
196
+ case "ipv4":
197
+ c.glyphicon = "glyphicon-resize-full";
198
+ c.group = 30;
199
+ c.group_method = "max";
200
+ break;
201
202
- // show max 10 mins of data
203
- if(c.points_to_show * c.group > 600) c.points_to_show = 600 / c.group;
202
+ case "conntrack":
203
+ c.glyphicon = "glyphicon-eye-open";
204
+ c.group = 30;
205
+ c.group_method = "max";
206
+ break;
207
205
- if(c.enabled) {
206
- var j;
207
- var h = "<div class=\"thumbgraph\"><table><tr><td><div class=\"thumbgraph\" id=\"" + c.div + "\"><table><tr><td align=\"center\" width=\"" + c.width + "\" height=\"" + c.height + "\"><h4><span class=\"glyphicon glyphicon-refresh\"></span><br/><br/>loading chart<br/><br/><span class=\"label label-default\">Please wait...</span></h4></td></tr></table></div></td></tr><tr><td align=\"center\"><div class=\"btn-group-xs\"><button type=\"button\" class=\"btn btn-default\" onclick=\"setMainChart(" + i +");\"> select " + c.name + " for zoom </button></div></td></tr></table></div>";
208
+ case "ipvs":
209
+ c.glyphicon = "glyphicon-sort";
210
+ c.group = 30;
211
+ c.group_method = "max";
212
+ break;
213
209
- // find the categories object for this type
210
- for(j = 0; j < categories.length ;j++) {
211
- if(categories[j].name == c.type) {
212
- categories[j].html += h;
213
- categories[j].count++;
214
+ case "disk":
215
+ c.glyphicon = "glyphicon-floppy-disk";
216
+ c.group = 20;
217
+ c.group_method = "max";
218
break;
215
- }
216
- }
219
218
- if(j == categories.length) {
219
- var t = "(as " + c.group_method + " every " + (c.group*c.update_every) + " seconds)";
220
- categories.push({name: c.type, title: c.category, description: t, priority: 0, count: 1, glyphicon: c.glyphicon, html: h});
220
+ default:
221
+ c.glyphicon = "glyphicon-search";
222
+ c.group = 60;
223
+ c.group_method = "max";
224
+ break;
225
}
222
- }
223
- });
226
225
- $.each(categories, function(i, a) {
226
- if(a.name == "net") a.priority = 1;
227
- else if(a.name == "tc") a.priority = 2;
228
- else if(a.name == "conntrack") a.priority = 3;
229
- else if(a.name == "ipvs") a.priority = 4;
230
- else if(a.name == "ipv4") a.priority = 5;
231
- else if(a.name == "disk") a.priority = 6;
232
- else a.priority = 4;
227
+ // calculate the time to refresh each chart
228
+ c.chart_update_every = c.group * 1000; // milliseconds
229
234
- a.html = "<tr><td><ol class=\"breadcrumb graphs\"><li class=\"active\"><span class=\"glyphicon " + a.glyphicon + "\"></span> <a id=\"" + a.name + "\" href=\"#" + a.name + "\"><b>" + a.title + "</b> " + a.description + " </a></li></ol></td></tr><tr><td><div class=\"thumbgraphs\">" + a.html + "</td></tr>";
235
- });
230
+ // calculate how many point to show for each chart
231
+ c.points_to_show = Math.round(c.entries / c.group) - 1;
232
237
- function categoriessort(a, b) {
238
- if(a.priority < b.priority) return -1;
239
- return 1;
240
- }
241
- categories.sort(categoriessort);
233
+ // show max 10 mins of data
234
+ if(c.points_to_show * c.group > 600) c.points_to_show = 600 / c.group;
235
243
- // combine all the htmls into one
244
- var allcategories = "<table width=\"100%\">";
245
- $.each(categories, function(i, a) {
246
- allcategories += a.html;
247
- });
248
- allcategories += "</table>";
236
+ if(c.enabled) {
237
+ var j;
238
+ var h = "<div class=\"thumbgraph\"><table><tr><td><div class=\"thumbgraph\" id=\"" + c.div + "\">" + chartIsLoadingHTML(c.chartOptions.width, c.chartOptions.height) + "</div></td></tr><tr><td align=\"center\"><div class=\"btn-group-xs\"><button type=\"button\" class=\"btn btn-default\" onclick=\"setMainChart(" + i +");\"> select " + c.name + " for zoom </button></div></td></tr></table></div>";
239
250
- scroll.innerHTML = allcategories;
251
- showThumbGraphs();
252
- };
240
+ // find the categories object for this type
241
+ for(j = 0; j < categories.length ;j++) {
242
+ if(categories[j].name == c.type) {
243
+ categories[j].html += h;
244
+ categories[j].count++;
245
+ break;
246
+ }
247
+ }
248
254
- var last_mini = 0;
255
- function myChartsRefreshInternal(howmany) {
256
- var ot = go_thumbs;
257
- var om = go_main;
249
+ if(j == categories.length) {
250
+ var t = "(as " + c.group_method + " every " + (c.group*c.update_every) + " seconds)";
251
+ categories.push({name: c.type, title: c.category, description: t, priority: 0, count: 1, glyphicon: c.glyphicon, html: h});
252
+ }
253
+ }
254
+ });
255
+
256
+ $.each(categories, function(i, a) {
257
+ if(a.name == "net") a.priority = 1;
258
+ else if(a.name == "tc") a.priority = 2;
259
+ else if(a.name == "conntrack") a.priority = 3;
260
+ else if(a.name == "ipvs") a.priority = 4;
261
+ else if(a.name == "ipv4") a.priority = 5;
262
+ else if(a.name == "disk") a.priority = 6;
263
+ else a.priority = 4;
264
+
265
+ a.html = "<tr><td><ol class=\"breadcrumb graphs\"><li class=\"active\"><span class=\"glyphicon " + a.glyphicon + "\"></span> <a id=\"" + a.name + "\" href=\"#" + a.name + "\"><b>" + a.title + "</b> " + a.description + " </a></li></ol></td></tr><tr><td><div class=\"thumbgraphs\">" + a.html + "</td></tr>";
266
+ });
267
+
268
+ function categoriessort(a, b) {
269
+ if(a.priority < b.priority) return -1;
270
+ return 1;
271
+ }
272
+ categories.sort(categoriessort);
273
259
- go_thumbs = 0;
260
- go_main = 0;
274
+ // combine all the htmls into one
275
+ var allcategories = "<table width=\"100%\">";
276
+ $.each(categories, function(i, a) {
277
+ allcategories += a.html;
278
+ });
279
+ allcategories += "</table>";
280
262
- var now = new Date().getTime();
281
+ thumbsContainer.innerHTML = allcategories;
282
+ showThumbGraphs();
283
+ });
284
+ }
285
264
- // refresh the main chart
265
- if(om && mainchart && (now - mainchart.last_updated) >= mainchart.chart_update_every) {
266
- refreshChart(mainchart);
267
- mainchart.last_updated = now;
268
- }
269
- go_main = om;
286
+ var last_mini = 0;
287
+ function thumbChartsRefreshInternal(howmany) {
288
+ if(mycharts.length == 0 || mode != MODE_THUMBS) return;
289
271
- // refresh a few of the thumbcharts
272
- if(mycharts.length == 0 || !ot) return;
290
+ var now = new Date().getTime();
291
292
// refresh the mini charts
293
var wanted = howmany;
@@ -281,43 +299,53 @@
299
if(last_mini >= mycharts.length) last_mini = 0;
300
301
if(!mycharts[last_mini].enabled) continue;
284
- if(!mycharts[last_mini].needs_refresh && now - mycharts[last_mini].last_updated < mycharts[last_mini].chart_update_every) continue;
302
+ if((now - mycharts[last_mini].last_updated) < mycharts[last_mini].chart_update_every) continue;
303
304
if(mycharts[last_mini].chart != null)
305
if(mycharts[last_mini].chart.getSelection()[0]) continue;
306
289
- refreshChart(mycharts[last_mini]);
307
+ if($('#' + mycharts[last_mini].div).visible(true) == false) continue;
308
+
309
+ refreshChart(mycharts[last_mini], mycharts[last_mini].last_updated?triggerThumbChartsRefresh:triggerThumbChartsRefreshFast);
310
mycharts[last_mini].last_updated = now;
311
312
did++;
293
- mycharts[last_mini].needs_refresh = false;
313
}
314
296
- go_thumbs = ot;
315
+ if(did == 0) triggerThumbChartsRefresh();
316
+ }
317
+
318
+ function triggerThumbChartsRefresh() {
319
+ setTimeout(thumbChartsRefresh, 500);
320
}
321
299
- function myChartsRefresh() {
300
- myChartsRefreshInternal(1);
322
+ function triggerThumbChartsRefreshFast() {
323
+ thumbChartsRefresh();
324
}
325
303
- setInterval(myChartsRefresh, 500);
326
+ function thumbChartsRefresh() {
327
+ if(mode == MODE_THUMBS) thumbChartsRefreshInternal(1);
328
+ }
329
+
330
+ // setInterval(myChartsRefresh, 500);
331
332
window.onresize = function(event) {
333
resizeCharts();
307
- drawCharts();
334
};
335
336
function showMainGraph() {
337
if(!mainchart) return;
338
+ mode = MODE_MAIN;
339
340
document.getElementById('maingraph_container').style.display = 'block';
341
document.getElementById('thumbgraphs_container').style.display = 'none';
342
316
- go_thumbs = 0;
317
- go_main = 1;
343
+ mainChartRefresh();
344
}
345
346
function showThumbGraphs() {
347
+ mode = MODE_THUMBS;
348
+
349
document.getElementById('maingraph_container').style.display = 'none';
350
document.getElementById('thumbgraphs_container').style.display = 'block';
351
@@ -326,8 +354,7 @@
354
mainchart = null;
355
}
356
329
- go_thumbs = 1;
330
- go_main = 0;
357
+ thumbChartsRefresh(1);
358
}
359
360
</script>
@@ -359,7 +386,7 @@
386
</div>
387
</div>
388
362
- <div class="container graphs" id="maingraph_container"">
389
+ <div class="container graphs" id="maingraph_container" style="display: none">
390
<table>
391
<tr><td><ol class="breadcrumb graphs"><li class="active"><a id="maingraph_title" href="#maingraph"><b> Maingraph </b></a></li></ol></td></tr>
392
<tr><td>
@@ -375,8 +402,7 @@
402
403
<div class="container graphs" id="thumbgraphs_container">
404
<div class="allgraphs" id="graphs">
405
+ <table width="100%"><tr><td align="center"><p/> <p/> <p/> <h1><span class="glyphicon glyphicon-refresh"></span><br/><br/>loading charts<br/><br/><span class="label label-default">Please wait...</span></h1></td></tr></table>
406
</div>
407
</div>
380
-
381
- <script type="text/javascript">initCharts();</script>
408
</html>
web/jquery.visible.js
new
+27
@@ -0,0 +1,27 @@
1
+(function($){
2
+
3
+ /**
4
+ * Copyright 2012, Digital Fusion
5
+ * Licensed under the MIT license.
6
+ * http://teamdf.com/jquery-plugins/license/
7
+ *
8
+ * @author Sam Sehnert
9
+ * @desc A small plugin that checks whether elements are within
10
+ * the user visible viewport of a web browser.
11
+ * only accounts for vertical position, not horizontal.
12
+ */
13
+ $.fn.visible = function(partial){
14
+
15
+ var $t = $(this),
16
+ $w = $(window),
17
+ viewTop = $w.scrollTop(),
18
+ viewBottom = viewTop + $w.height(),
19
+ _top = $t.offset().top,
20
+ _bottom = _top + $t.height(),
21
+ compareTop = partial === true ? _bottom : _top,
22
+ compareBottom = partial === true ? _top : _bottom;
23
+
24
+ return ((compareBottom <= viewBottom) && (compareTop >= viewTop));
25
+ };
26
+
27
+})(jQuery);
\ No newline at end of file
web/netdata.js
+144
-91
@@ -4,7 +4,7 @@ if(!window.console){ window.console = {log: function(){} }; }
4
// Load the Visualization API and the piechart package.
5
google.load('visualization', '1', {'packages':['corechart']});
6
7
-function refreshChart(chart) {
7
+function refreshChart(chart, doNext) {
8
chart.refreshCount++;
9
10
if(chart.chart != null) {
@@ -17,70 +17,39 @@ function refreshChart(chart) {
17
url += chart.group?chart.group.toString():"1";
18
url += "/";
19
url += chart.group_method?chart.group_method:"average";
20
- chart.jsondata = $.ajax({
20
+
21
+ $.ajax({
22
url: url,
23
dataType:"json",
23
- async: false,
24
cache: false
25
- }).responseText;
26
-
27
- if(!chart.jsondata || chart.jsondata.length == 0) return;
28
-
29
- // Create our data table out of JSON data loaded from server.
30
- chart.datatable = new google.visualization.DataTable(chart.jsondata);
31
-
32
- // setup the default options
33
- var options = {
34
- width: chart.width,
35
- height: chart.height,
36
- title: chart.title,
37
- hAxis: {title: "Time of Day"},
38
- vAxis: {title: chart.vtitle, minValue: 10},
39
- focusTarget: 'category',
40
- explorer: (chart.explorer)?true:false,
41
- // animation: {duration: 1000, easing: 'inAndOut'},
42
- };
43
-
44
- // disable interactivity on thumbnails
45
- if(chart.thumbnail) options.enableInteractivity = false;
46
-
47
- // hide axis titles if too small
48
- if(chart.height < 200) options.vAxis.title = null;
49
- if(chart.width < 350) options.hAxis.title = null;
50
-
51
- if(chart.name.substring(0, 5) == "ipv4." || chart.name.substring(0, 10) == "conntrack." || chart.name.substring(0, 5) == "ipvs.") {
52
- options.lineWidth = 3;
53
- options.curveType = 'function';
54
- }
55
- else if(chart.name.substring(0, 3) == "tc.") {
56
- options.isStacked = true;
57
- options.title += " [stacked]";
58
- options.areaOpacity = 1.0;
59
- options.lineWidth = 1;
60
- }
61
- else {
62
- options.areaOpacity = 0.3;
63
- options.lineWidth = 2;
64
- }
25
+ }).done(function(jsondata) {
26
+ if(!jsondata || jsondata.length == 0) return;
27
+ chart.jsondata = jsondata;
28
+
29
+ // Create our data table out of JSON data loaded from server.
30
+ chart.datatable = new google.visualization.DataTable(chart.jsondata);
31
+
32
+ // cleanup once every 50 updates
33
+ // we don't cleanup on every single, to avoid firefox flashing effect
34
+ if(chart.chart && chart.refreshCount > 50) {
35
+ chart.chart.clearChart();
36
+ chart.chart = null;
37
+ }
38
66
- // cleanup once every 100 updates
67
- // we don't cleanup on every single, to avoid firefox flashing effect
68
- if(chart.chart && chart.refreshCount > 100) {
69
- chart.chart.clearChart();
70
- chart.chart = null;
71
- }
39
+ // Instantiate and draw our chart, passing in some options.
40
+ if(!chart.chart) {
41
+ console.log('Creating new chart for ' + chart.url);
42
+ if(chart.chartType == "LineChart")
43
+ chart.chart = new google.visualization.LineChart(document.getElementById(chart.div));
44
+ else
45
+ chart.chart = new google.visualization.AreaChart(document.getElementById(chart.div));
46
+ }
47
+
48
+ if(chart.chart) chart.chart.draw(chart.datatable, chart.chartOptions);
49
+ else console.log('Cannot create chart for ' + chart.url);
50
73
- // Instantiate and draw our chart, passing in some options.
74
- if(!chart.chart) {
75
- console.log('Creating new chart for ' + chart.url);
76
- if(chart.name.substring(0, 5) == "ipv4." || chart.name.substring(0, 10) == "conntrack." || chart.name.substring(0, 5) == "ipvs.")
77
- chart.chart = new google.visualization.LineChart(document.getElementById(chart.div));
78
- else
79
- chart.chart = new google.visualization.AreaChart(document.getElementById(chart.div));
80
- }
81
-
82
- if(chart.chart) chart.chart.draw(chart.datatable, options);
83
- else console.log('Cannot create chart for ' + chart.url);
51
+ if(typeof doNext == "function") doNext();
52
+ });
53
}
54
55
// loadCharts()
@@ -88,35 +57,111 @@ function refreshChart(chart) {
57
// returns an array of objects, containing all the server metadata
58
// (not the values of the graphs - just the info about the graphs)
59
91
-function loadCharts() {
92
- var mycharts = new Array();
93
-
60
+function loadCharts(doNext) {
61
$.ajax({
62
url: '/all.json',
96
- async: false,
63
dataType: 'json',
98
- success: function (json) { mycharts = json.charts; }
99
- });
64
+ cache: false
65
+ }).done(function(json) {
66
+ $.each(json.charts, function(i, value) {
67
+ json.charts[i].div = json.charts[i].name.replace(/\./g,"_");
68
+ json.charts[i].div = json.charts[i].div.replace(/\-/g,"_");
69
+ json.charts[i].div = json.charts[i].div + "_div";
70
101
- $.each(mycharts, function(i, value) {
102
- mycharts[i].div = mycharts[i].name.replace(/\./g,"_");
103
- mycharts[i].div = mycharts[i].div.replace(/\-/g,"_");
104
- mycharts[i].div = mycharts[i].div + "_div";
105
-
106
- mycharts[i].width = 0;
107
- mycharts[i].height = 0;
108
- mycharts[i].thumbnail = false;
109
- mycharts[i].refreshCount = 0;
110
- mycharts[i].group = 1;
111
- mycharts[i].points_to_show = 0; // all
112
- mycharts[i].group_method = "average";
113
-
114
- mycharts[i].chart = null;
115
- mycharts[i].jsondata = null;
116
- mycharts[i].datatable = null;
117
- });
71
+ json.charts[i].thumbnail = false;
72
+ json.charts[i].refreshCount = 0;
73
+ json.charts[i].group = 1;
74
+ json.charts[i].points_to_show = 0; // all
75
+ json.charts[i].group_method = "max";
76
+
77
+ json.charts[i].chart = null;
78
+ json.charts[i].jsondata = null;
79
+ json.charts[i].datatable = null;
80
+
81
+ // if the user has given a title, use it
82
+ if(json.charts[i].usertitle) json.charts[i].title = json.charts[i].usertitle;
83
+
84
+ // check if the userpriority is IGNORE
85
+ if(json.charts[i].userpriority == "IGNORE")
86
+ json.charts[i].enabled = false;
87
+ else
88
+ json.charts[i].enabled = true;
89
+
90
+ // set default chart options
91
+ json.charts[i].chartOptions = {
92
+ lineWidth: 2,
93
+ title: json.charts[i].title,
94
+ hAxis: {title: "Time of Day"},
95
+ vAxis: {title: json.charts[i].vtitle, minValue: 10},
96
+ focusTarget: 'category',
97
+ };
98
+
99
+ // set the chart type
100
+ if((json.charts[i].type == "ipv4" || json.charts[i].type == "ipv6" || json.charts[i].type == "ipvs" || json.charts[i].type == "conntrack")
101
+ && json.charts[i].name != "ipv4.net" && json.charts[i].name != "ipvs.net") {
102
+
103
+ // default for all LineChart
104
+ json.charts[i].chartType = "LineChart";
105
+ json.charts[i].chartOptions.lineWidth = 3;
106
+ json.charts[i].chartOptions.curveType = 'function';
107
+ }
108
+ else if(json.charts[i].type == "tc") {
109
+
110
+ // default for all stacked AreaChart
111
+ json.charts[i].chartType = "AreaChart";
112
+ json.charts[i].chartOptions.isStacked = true;
113
+ json.charts[i].chartOptions.areaOpacity = 1.0;
114
+ json.charts[i].chartOptions.lineWidth = 1;
115
+
116
+ json.charts[i].group_method = "average";
117
+ }
118
+ else {
119
+
120
+ // default for all AreaChart
121
+ json.charts[i].chartType = "AreaChart";
122
+ json.charts[i].chartOptions.isStacked = false;
123
+ json.charts[i].chartOptions.areaOpacity = 0.3;
124
+ }
125
+
126
+ // the category name, and other options, per type
127
+ switch(json.charts[i].type) {
128
+ case "tc":
129
+ json.charts[i].category = "Quality of Service";
130
+ break;
131
+
132
+ case "net":
133
+ json.charts[i].category = "Network Interfaces";
134
119
- return mycharts;
135
+ // disable IFB and net.lo devices by default
136
+ if((json.charts[i].id.substring(json.charts[i].id.length - 4, json.charts[i].id.length) == "-ifb")
137
+ || json.charts[i].id == "net.lo")
138
+ json.charts[i].enabled = false;
139
+ break;
140
+
141
+ case "ipv4":
142
+ json.charts[i].category = "IPv4";
143
+ break;
144
+
145
+ case "conntrack":
146
+ json.charts[i].category = "Netfilter";
147
+ break;
148
+
149
+ case "ipvs":
150
+ json.charts[i].category = "IPVS";
151
+ break;
152
+
153
+ case "disk":
154
+ json.charts[i].category = "Disk I/O";
155
+ break;
156
+
157
+ default:
158
+ json.charts[i].category = "Unknown";
159
+ break;
160
+ }
161
+ });
162
+
163
+ if(typeof doNext == "function") doNext(json.charts);
164
+ });
165
};
166
167
var charts = new Array();
@@ -133,14 +178,22 @@ function addChart(name, div, width, height, jsonurl, title, vtitle) {
178
179
charts[i].div = div;
180
136
- charts[i].width = width;
137
- charts[i].height = height;
181
charts[i].refreshCount = 0;
182
charts[i].thumbnail = false;
183
184
charts[i].chart = null;
185
charts[i].jsondata = null;
186
charts[i].datatable = null;
187
+
188
+ charts[i].chartType = "AreaChart";
189
+ charts[i].chartOptions = {
190
+ width: width,
191
+ height: height,
192
+ title: charts[i].title,
193
+ hAxis: {title: "Time of Day"},
194
+ vAxis: {title: charts[i].vtitle, minValue: 10},
195
+ focusTarget: 'category',
196
+ };
197
}
198
199
var charts_last_drawn = 999999999;
@@ -188,9 +241,9 @@ function refreshCharts(howmany) {
241
charts_last_drawn++;
242
if(charts_last_drawn >= charts.length) charts_last_drawn = 0;
243
191
- if(charts[charts_last_drawn].width == 0 && charts[charts_last_drawn].height == 0) {
192
- charts[charts_last_drawn].width = width;
193
- charts[charts_last_drawn].height = height;
244
+ if(charts[charts_last_drawn].chartOptions.width == 0 && charts[charts_last_drawn].height == 0) {
245
+ charts[charts_last_drawn].chartOptions.width = width;
246
+ charts[charts_last_drawn].chartOptions.height = height;
247
zeroDimensions = 1;
248
}
249
@@ -204,8 +257,8 @@ function refreshCharts(howmany) {
257
}
258
259
if(zeroDimensions == 1) {
207
- charts[charts_last_drawn].width = 0;
208
- charts[charts_last_drawn].height = 0;
260
+ charts[charts_last_drawn].chartOptions.width = 0;
261
+ charts[charts_last_drawn].chartOptions.height = 0;
262
}
263
}
264
return 0;