]> arthur.barton.de Git - netdata.git/blob - web/old/netdata.js
Add missing comma to README.md
[netdata.git] / web / old / netdata.js
1 // fix old IE bug with console
2 if(!window.console){ window.console = {log: function(){} }; }
3
4 // Load the Visualization API and the piechart package.
5 google.load('visualization', '1.1', {'packages':['corechart']});
6 //google.load('visualization', '1.1', {'packages':['controls']});
7
8 function canChartBeRefreshed(chart) {
9         // is it enabled?
10         if(!chart.enabled) return false;
11
12         // is there something selected on the chart?
13         if(chart.chart && chart.chart.getSelection()[0]) return false;
14
15         // is it too soon for a refresh?
16         var now = Date.now();
17         if((now - chart.last_updated) < (chart.group * chart.update_every * 1000)) return false;
18
19         // is the chart in the visible area?
20         //console.log(chart.div);
21         if($('#' + chart.div).visible(true) == false) return false;
22
23         // ok, do it
24         return true;
25 }
26
27 function generateChartURL(chart) {
28         // build the data URL
29         var url = chart.url;
30         url += chart.points_to_show?chart.points_to_show.toString():"all";
31         url += "/";
32         url += chart.group?chart.group.toString():"1";
33         url += "/";
34         url += chart.group_method?chart.group_method:"average";
35         url += "/";
36         url += chart.after?chart.after.toString():"0";
37         url += "/";
38         url += chart.before?chart.before.toString():"0";
39         url += "/";
40         url += chart.non_zero?"nonzero":"all";
41         url += "/";
42
43         return url;
44 }
45
46 function renderChart(chart, doNext) {
47         if(canChartBeRefreshed(chart) == false) return false;
48
49         $.ajax({
50                 url: generateChartURL(chart),
51                 dataType:"json",
52                 cache: false
53         })
54         .done(function(jsondata) {
55                 if(!jsondata || jsondata.length == 0) return;
56                 chart.jsondata = jsondata;
57
58                 // Create our data table out of JSON data loaded from server.
59                 chart.datatable = new google.visualization.DataTable(chart.jsondata);
60                 //console.log(chart.datatable);
61
62                 // cleanup once every 50 updates
63                 // we don't cleanup on every single, to avoid firefox flashing effect
64                 if(chart.chart && chart.refreshCount > 50) {
65                         chart.chart.clearChart();
66                         chart.chart = null;
67                         chart.refreshCount = 0;
68                 }
69
70                 // Instantiate and draw our chart, passing in some options.
71                 if(!chart.chart) {
72                         // console.log('Creating new chart for ' + chart.url);
73                         if(chart.chartType == "LineChart")
74                                 chart.chart = new google.visualization.LineChart(document.getElementById(chart.div));
75                         else
76                                 chart.chart = new google.visualization.AreaChart(document.getElementById(chart.div));
77                 }
78
79                 if(chart.chart) {
80                         chart.chart.draw(chart.datatable, chart.chartOptions);
81                         chart.refreshCount++;
82                         chart.last_updated = Date.now();
83                 }
84                 else console.log('Cannot create chart for ' + chart.url);
85         })
86         .fail(function() {
87                 // to avoid an infinite loop, let's assume it was refreshed
88                 if(chart.chart) chart.chart.clearChart();
89                 chart.chart = null;
90                 chart.refreshCount = 0;
91                 showChartIsLoading(chart.div, chart.name, chart.chartOptions.width, chart.chartOptions.height, "failed to refresh");
92                 chart.last_updated = Date.now();
93         })
94         .always(function() {
95                 if(typeof doNext == "function") doNext();
96         });
97
98         return true;
99 }
100
101 function chartIsLoadingHTML(name, width, height, message)
102 {
103         return "<table><tr><td align=\"center\" width=\"" + width + "\" height=\"" + height + "\" style=\"vertical-align:middle\"><h4><span class=\"glyphicon glyphicon-refresh\"></span><br/><br/>" + name + "<br/><br/><span class=\"label label-default\">" + (message?message:"loading chart...") + "</span></h4></td></tr></table>";
104 }
105
106 function showChartIsLoading(id, name, width, height, message) {
107         document.getElementById(id).innerHTML = chartIsLoadingHTML(name, width, height, message);
108 }
109
110 // calculateChartPointsToShow
111 // calculate the chart group and point to show properties.
112 // This uses the chartOptions.width and the supplied divisor
113 // to calculate the propers values so that the chart will
114 // be visually correct (not too much or too less points shown).
115 //
116 // c = the chart
117 // divisor = when calculating screen points, divide width with this
118 //           if all screen points are used the chart will be overcrowded
119 //           the default is 2
120 // maxtime = the maxtime to show
121 //           the default is to render all the server data
122 // group   = the required grouping on points
123 //           if undefined or negative, any calculated value will be used
124 //           if zero, one of 1,2,5,10,15,20,30,45,60 will be used
125
126 function calculateChartPointsToShow(c, divisor, maxtime, group, enable_curve) {
127         // console.log('calculateChartPointsToShow( c = ' + c.id + ',  divisor = ' + divisor + ', maxtime = ' + maxtime + ', group = ' + group + ' )');
128
129         if(!divisor) divisor = 2;
130
131         var before = c.before?c.before:Date.now() / 1000;
132         var after = c.after?c.after:c.first_entry_t;
133
134         var dt = before - after;
135         if(dt > c.entries * c.update_every) dt = c.entries * c.update_every;
136
137         // console.log('chart ' + c.id + ' internal duration is ' + dt + ' secs, requested maxtime is ' + maxtime + ' secs');
138
139         if(!maxtime) maxtime = c.entries * c.update_every;
140         dt = maxtime;
141
142         var data_points = Math.round(dt / c.update_every);
143         if(!data_points) data_points = 100;
144
145         var screen_points = Math.round(c.chartOptions.width / divisor);
146         if(!screen_points) screen_points = 100;
147
148         // console.log('screen_points = ' + screen_points + ', data_points = ' + data_points + ', divisor = ' + divisor);
149
150         if(group == undefined || group <= 0) {
151                 if(screen_points > data_points) {
152                         c.group = 1;
153                         c.points_to_show = data_points;
154                         // console.log("rendering at full detail (group = " + c.group + ", points_to_show = " + c.points_to_show + ')');
155                 }
156                 else {
157                         c.group = Math.round(data_points / screen_points);
158
159                              if(c.group > 60) c.group = 90;
160                         else if(c.group > 45) c.group = 60;
161                         else if(c.group > 30) c.group = 45;
162                         else if(c.group > 20) c.group = 30;
163                         else if(c.group > 15) c.group = 20;
164                         else if(c.group > 10) c.group = 15;
165                         else if(c.group > 5) c.group = 10;
166                         else if(c.group > 4) c.group = 5;
167                         else if(c.group > 3) c.group = 4;
168                         else if(c.group > 2) c.group = 3;
169                         else if(c.group > 1) c.group = 2;
170                         else c.group = 1;
171
172                         c.points_to_show = Math.round(data_points / c.group);
173                         // console.log("rendering adaptive (group = " + c.group + ", points_to_show = " + c.points_to_show + ')');
174                 }
175         }
176         else {
177                 c.group = group;
178                 c.points_to_show = Math.round(data_points / group);
179                 // console.log("rendering with supplied group (group = " + c.group + ", points_to_show = " + c.points_to_show + ')');
180         }
181
182         // console.log("final configuration (group = " + c.group + ", points_to_show = " + c.points_to_show + ')');
183
184         // make sure the line width is not congesting the chart
185         if(c.chartType == 'LineChart') {
186                 if(c.points_to_show > c.chartOptions.width / 3) {
187                         c.chartOptions.lineWidth = 1;
188                 }
189
190                 else {
191                         c.chartOptions.lineWidth = 2;
192                 }
193         }
194         else if(c.chartType == 'AreaChart') {
195                 if(c.points_to_show > c.chartOptions.width / 2)
196                         c.chartOptions.lineWidth = 0;
197                 else
198                         c.chartOptions.lineWidth = 1;
199         }
200
201         // do not render curves when we don't have at
202         // least 2 twice the space per point
203         if(!enable_curve || c.points_to_show > (c.chartOptions.width * c.chartOptions.lineWidth / 2) )
204                 c.chartOptions.curveType = 'none';
205         else
206                 c.chartOptions.curveType = c.default_curveType;
207
208         var hpoints = Math.round(maxtime / 30);
209         if(hpoints > 10) hpoints = 10;
210         c.chartOptions.hAxis.gridlines.count = hpoints;
211 }
212
213
214 // loadCharts()
215 // fetches all the charts from the server
216 // returns an array of objects, containing all the server metadata
217 // (not the values of the graphs - just the info about the graphs)
218
219 function loadCharts(base_url, doNext) {
220         $.ajax({
221                 url: ((base_url)?base_url:'') + '/all.json',
222                 dataType: 'json',
223                 cache: false
224         })
225         .done(function(json) {
226                 $.each(json.charts, function(i, value) {
227                         json.charts[i].div = json.charts[i].name.replace(/\./g,"_");
228                         json.charts[i].div = json.charts[i].div.replace(/\-/g,"_");
229                         json.charts[i].div = json.charts[i].div + "_div";
230
231                         // make sure we have the proper values
232                         if(!json.charts[i].update_every) chart.update_every = 1;
233                         if(base_url) json.charts[i].url = base_url + json.charts[i].url;
234
235                         json.charts[i].last_updated = 0;
236                         json.charts[i].thumbnail = false;
237                         json.charts[i].refreshCount = 0;
238                         json.charts[i].group = 1;
239                         json.charts[i].points_to_show = 0;      // all
240                         json.charts[i].group_method = "max";
241
242                         json.charts[i].chart = null;
243                         json.charts[i].jsondata = null;
244                         json.charts[i].datatable = null;
245                         json.charts[i].before = 0;
246                         json.charts[i].after = 0;
247
248                         // if it is detail, disable it by default
249                         if(json.charts[i].isdetail) json.charts[i].enabled = false;
250
251                         // set default chart options
252                         json.charts[i].chartOptions = {
253                                 width: 400,
254                                 height: 200,
255                                 lineWidth: 1,
256                                 title: json.charts[i].title,
257                                 fontSize: 11,
258                                 hAxis: {
259                                 //      title: "Time of Day",
260                                 //      format:'HH:mm:ss',
261                                         viewWindowMode: 'maximized',
262                                         slantedText: false,
263                                         format:'HH:mm:ss',
264                                         textStyle: {
265                                                 fontSize: 9
266                                         },
267                                         gridlines: {
268                                                 color: '#EEE'
269                                         }
270                                 },
271                                 vAxis: {
272                                         title: json.charts[i].units,
273                                         viewWindowMode: 'pretty',
274                                         minValue: -0.1,
275                                         maxValue: 0.1,
276                                         direction: 1,
277                                         textStyle: {
278                                                 fontSize: 9
279                                         },
280                                         gridlines: {
281                                                 color: '#EEE'
282                                         }
283                                 },
284                                 chartArea: {
285                                         width: '65%',
286                                         height: '80%'
287                                 },
288                                 focusTarget: 'category',
289                                 annotation: {
290                                         '1': {
291                                                 style: 'line'
292                                         }
293                                 },
294                                 pointsVisible: 0,
295                                 titlePosition: 'out',
296                                 titleTextStyle: {
297                                         fontSize: 11
298                                 },
299                                 tooltip: {
300                                         isHtml: true,
301                                         ignoreBounds: true,
302                                         textStyle: {
303                                                 fontSize: 9
304                                         }
305                                 }
306                         };
307
308                         json.charts[i].default_curveType = 'none';
309
310                         // set the chart type
311                         switch(json.charts[i].chart_type) {
312                                 case "area":
313                                         json.charts[i].chartType = "AreaChart";
314                                         json.charts[i].chartOptions.isStacked = false;
315                                         json.charts[i].chartOptions.areaOpacity = 0.3;
316
317                                         json.charts[i].chartOptions.vAxis.viewWindowMode = 'maximized';
318                                         json.charts[i].non_zero = 0;
319
320                                         json.charts[i].group = 3;
321                                         break;
322
323                                 case "stacked":
324                                         json.charts[i].chartType = "AreaChart";
325                                         json.charts[i].chartOptions.isStacked = true;
326                                         json.charts[i].chartOptions.areaOpacity = 0.85;
327                                         json.charts[i].chartOptions.lineWidth = 1;
328                                         json.charts[i].group_method = "average";
329                                         json.charts[i].non_zero = 1;
330
331                                         json.charts[i].chartOptions.vAxis.viewWindowMode = 'maximized';
332                                         json.charts[i].chartOptions.vAxis.minValue = null;
333                                         json.charts[i].chartOptions.vAxis.maxValue = null;
334
335                                         json.charts[i].group = 10;
336                                         break;
337
338                                 default:
339                                 case "line":
340                                         json.charts[i].chartType = "LineChart";
341                                         json.charts[i].chartOptions.lineWidth = 2;
342                                         json.charts[i].non_zero = 0;
343
344                                         json.charts[i].default_curveType = 'function';
345
346                                         json.charts[i].group = 3;
347                                         break;
348                         }
349
350                         // the category name, and other options, per type
351                         switch(json.charts[i].type) {
352                                 case "system":
353                                         json.charts[i].category = "System";
354                                         json.charts[i].categoryPriority = 10;
355                                         json.charts[i].glyphicon = "glyphicon-dashboard";
356
357                                         if(json.charts[i].id == "system.cpu" || json.charts[i].id == "system.ram") {
358                                                 json.charts[i].chartOptions.vAxis.minValue = 0;
359                                                 json.charts[i].chartOptions.vAxis.maxValue = 100;
360                                         }
361                                         else {
362                                                 json.charts[i].chartOptions.vAxis.minValue = -0.1;
363                                                 json.charts[i].chartOptions.vAxis.maxValue =  0.1;
364                                         }
365                                         break;
366
367                                 case "net":
368                                         json.charts[i].category = "Network";
369                                         json.charts[i].categoryPriority = 20;
370                                         json.charts[i].glyphicon = "glyphicon-transfer";
371
372                                         // disable IFB and net.lo devices by default
373                                         if((json.charts[i].id.substring(json.charts[i].id.length - 4, json.charts[i].id.length) == "-ifb")
374                                                 || json.charts[i].id == "net.lo")
375                                                 json.charts[i].enabled = false;
376                                         break;
377
378                                 case "tc":
379                                         json.charts[i].category = "Quality of Service";
380                                         json.charts[i].categoryPriority = 30;
381                                         json.charts[i].glyphicon = "glyphicon-random";
382                                         break;
383
384                                 case "ipvs":
385                                         json.charts[i].category = "IP Virtual Server";
386                                         json.charts[i].categoryPriority = 40;
387                                         json.charts[i].glyphicon = "glyphicon-sort";
388                                         break;
389
390                                 case "netfilter":
391                                         json.charts[i].category = "Netfilter";
392                                         json.charts[i].categoryPriority = 50;
393                                         json.charts[i].glyphicon = "glyphicon-cloud";
394                                         break;
395
396                                 case "ipv4":
397                                         json.charts[i].category = "IPv4";
398                                         json.charts[i].categoryPriority = 60;
399                                         json.charts[i].glyphicon = "glyphicon-globe";
400                                         break;
401
402                                 case "mem":
403                                         json.charts[i].category = "Memory";
404                                         json.charts[i].categoryPriority = 70;
405                                         json.charts[i].glyphicon = "glyphicon-dashboard";
406                                         break;
407
408                                 case "cpu":
409                                         json.charts[i].category = "CPU";
410                                         json.charts[i].categoryPriority = 80;
411                                         json.charts[i].glyphicon = "glyphicon-dashboard";
412
413                                         if(json.charts[i].id.substring(0, 7) == "cpu.cpu") {
414                                                 json.charts[i].chartOptions.vAxis.minValue = 0;
415                                                 json.charts[i].chartOptions.vAxis.maxValue = 100;
416                                         }
417                                         break;
418
419                                 case "disk":
420                                         json.charts[i].category = "Disks";
421                                         json.charts[i].categoryPriority = 90;
422                                         json.charts[i].glyphicon = "glyphicon-hdd";
423                                         break;
424
425                                 case "nfsd":
426                                         json.charts[i].category = "NFS Server";
427                                         json.charts[i].categoryPriority = 100;
428                                         json.charts[i].glyphicon = "glyphicon-hdd";
429                                         break;
430
431                                 case "nut":
432                                         json.charts[i].category = "UPS";
433                                         json.charts[i].categoryPriority = 110;
434                                         json.charts[i].glyphicon = "glyphicon-dashboard";
435                                         break;
436
437                                 case "netdata":
438                                         json.charts[i].category = "NetData";
439                                         json.charts[i].categoryPriority = 3000;
440                                         json.charts[i].glyphicon = "glyphicon-thumbs-up";
441                                         break;
442
443                                 case "apps":
444                                         json.charts[i].category = "Apps";
445                                         json.charts[i].categoryPriority = 4000;
446                                         json.charts[i].glyphicon = "glyphicon-tasks";
447                                         break;
448
449                                 case "squid":
450                                         json.charts[i].category = "Squid";
451                                         json.charts[i].categoryPriority = 5000;
452                                         json.charts[i].glyphicon = "glyphicon-link";
453                                         break;
454
455                                 case "example":
456                                         json.charts[i].category = "Examples";
457                                         json.charts[i].categoryPriority = 9000;
458                                         json.charts[i].glyphicon = "glyphicon-search";
459                                         break;
460
461                                 default:
462                                         json.charts[i].category = json.charts[i].type;
463                                         json.charts[i].categoryPriority = 1000;
464                                         json.charts[i].glyphicon = "glyphicon-search";
465                                         break;
466                         }
467                 });
468
469                 if(typeof doNext == "function") doNext(json);
470         })
471         .fail(function() {
472                 if(typeof doNext == "function") doNext();
473         });
474 };
475
476 // jquery visible plugin
477 (function($){
478
479         /**
480          * Copyright 2012, Digital Fusion
481          * Licensed under the MIT license.
482          * http://teamdf.com/jquery-plugins/license/
483          *
484          * @author Sam Sehnert
485          * @desc A small plugin that checks whether elements are within
486          *               the user visible viewport of a web browser.
487          *               only accounts for vertical position, not horizontal.
488          */
489         $.fn.visible = function(partial){
490
491             var $t                              = $(this),
492                 $w                              = $(window),
493                 viewTop                 = $w.scrollTop(),
494                 viewBottom              = viewTop + $w.height(),
495                 _top                    = $t.offset().top,
496                 _bottom                 = _top + $t.height(),
497                 compareTop              = partial === true ? _bottom : _top,
498                 compareBottom   = partial === true ? _top : _bottom;
499
500                 return ((compareBottom <= viewBottom) && (compareTop >= viewTop));
501     };
502 })(jQuery);