@cryptotaxi247 / netdata-1 / commits / 405713ee7

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 +");\">&nbsp;&nbsp;select " + c.name + " for zoom&nbsp;&nbsp;</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> &nbsp; <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 +");\">&nbsp;&nbsp;select " + c.name + " for zoom&nbsp;&nbsp;</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> &nbsp; <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/>&nbsp;<p/>&nbsp;<p/>&nbsp;<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;