]> arthur.barton.de Git - netdata.git/blob - web/index.html
show null values on the legends on hover when the dimensions do not have data
[netdata.git] / web / index.html
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4     <title>netdata dashboard</title>
5     <meta name="application-name" content="netdata">
6
7     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
8     <meta charset="utf-8">
9     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
10     <meta name="viewport" content="width=device-width, initial-scale=1">
11     <meta name="apple-mobile-web-app-capable" content="yes">
12     <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
13     <meta name="author" content="costa@tsaousis.gr">
14
15     <!-- <link rel="shortcut icon" href="images/seo-performance-multi-size.ico"> -->
16
17     <!-- <link rel="apple-touch-icon" href="images/seo-performance-72.png"> -->
18     <!-- <link rel="apple-touch-icon" sizes="72x72" href="images/seo-performance-72.png"> -->
19     <!-- <link rel="apple-touch-icon" sizes="114x114" href="images/seo-performance-114.png"> -->
20
21     <!-- <link rel="icon" type="image/png" sizes="512x512" href="images/seo-performance-512.png"> -->
22     <!-- <link rel="icon" type="image/png" sizes="256x256" href="images/seo-performance-256.png"> -->
23     <!-- <link rel="icon" type="image/png" sizes="128x128" href="images/seo-performance-128.png"> -->
24     <!-- <link rel="icon" type="image/png" sizes="64x64" href="images/seo-performance-64.png"> -->
25     <!-- <link rel="icon" type="image/png" sizes="48x48" href="images/seo-performance-48.png"> -->
26     <!-- <link rel="icon" type="image/png" sizes="24x24" href="images/seo-performance-24.png"> -->
27     <!-- <link rel="icon" type="image/png" sizes="16x16" href="images/seo-performance-16.png"> -->
28     <!-- <link rel="icon" type="image/png" sizes="32x32" href="images/seo-performance-32.png"> -->
29
30     <link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACNklEQVRYhcXXv2tUQRAH8M+FEIJISBHCIWIhIQSUILERi4AiiqCggiIiomAjlhaC4j+ghYWISgqNohZaCBZBC8Ei8QdEUCutFBsxCBqDYkgci/cunkfuJffjJQPD8mZm5/vd2WV2HzlJ0Bs8CvrywsgCHwy+BpGOg0sJfjj4nYKX9FdwKG9gwZlgtgK8pLOpPxfw1mCoCnClDgWtzQTvCEYWCV7SkWAlFBoEb8dlDKBF8t2bMWUSH/AHr3CiEfz5CPUusPJLkRCdk5ZqyeqUrQv4R7E5TwK7M3zTeIKduRAIitiWEfIY69GdCwGcRFuG/xqONRkzkaA7+J5x+MaDtWmHvJ4HgeEM8Nn0bridfv9HoOFyBAdwJCPkqqTzHWwUaz7wgeBHxupfBKuCj2W25mxBsCGYyAB/FxTT27HcPlyep64tCLbjKbqqhLzBlgKfF8pVE4FgRXABI+ioEnYfOyzcFWsCbg+OV+xlpU4ER4O+4HVwL51b3xYEXcGu4Ao+YQhr5gmdxHmsQyfG0b/YxbWmLfRWmnxa0s06VbTMCpnBS9zFzQKTwR5cXCzwHIE02Sl8wSZsRI/kgLVJqjSd+t9LVjiG1diPszhdK3A5gR48k5zYMTwscC59sfT799CYKvA8EttbSeXgTr3gJQKl91kR+yTlvyG5uUbLYh9gb+ovltkb6qYtNSRo3kOygsBSzGlKsubf43USWLYK5CLLXoFWyU/CtzLbVDpW2n+m40yN9ukqdvAX9ac/EIgOapcAAAAASUVORK5CYII=">
31
32     <meta property="og:locale"             content="en_US" />
33     <meta property="og:url"                content="https://my-netdata.io" />
34     <meta property="og:type"               content="website" />
35     <meta property="og:site_name"          content="netdata"/>
36     <meta property="og:title"              content="Get control of your Linux Servers. Simple. Effective. Awesome." />
37     <meta property="og:description"        content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms." />
38     <meta property="og:image"              content="https://cloud.githubusercontent.com/assets/2662304/20910305/65d10354-bb69-11e6-8128-c44b547517b4.png" />
39     <meta property="og:image:type"         content="image/png" />
40     <meta property="fb:app_id"             content="1200089276712916" />
41
42     <meta name="twitter:card"              content="summary" />
43     <meta name="twitter:site"              content="@linuxnetdata" />
44     <meta name="twitter:title"             content="Get control of your Linux Servers. Simple. Effective. Awesome." />
45     <meta name="twitter:description"       content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms." />
46     <meta name="twitter:image"             content="https://cloud.githubusercontent.com/assets/2662304/14092712/93b039ea-f551-11e5-822c-beadbf2b2a2e.gif" />
47
48     <style>
49     /* prevent body from hiding under the navbar */
50     body {
51         padding-top: 50px;
52     }
53
54     .loadOverlay {
55         position: absolute;
56         top: 0px;
57         left: 0px;
58         width: 100%;
59         height:100%;
60         z-index: 2000;
61         font-size: 10vh;
62         font-family: sans-serif;
63         padding: 40vh 0 40vh 0;
64         font-weight: bold;
65         text-align: center;
66     }
67
68     .modal-wide .modal-dialog {
69         width: 80%;
70     }
71
72     /* fix # anchors scrolling under the navbar
73        https://github.com/twbs/bootstrap/issues/1768#issuecomment-46519033
74      */
75     h1 {
76         position: relative;
77         z-index: -1;
78     }
79     h2 {
80         position: relative;
81         z-index: -2;
82     }
83     h1:before, h2:before {
84         display: block;
85         content: " ";
86         margin-top: -70px;
87         height: 70px;
88         visibility: hidden;
89     }
90
91     .p {
92         display: block;
93         margin-top: 15px;
94     }
95
96     .option-row,
97     .option-control {
98         vertical-align: top;
99         padding: 10px;
100         padding-top: 30px;
101         padding-left: 30px;
102     }
103
104     .option-info {
105         padding: 10px;
106     }
107
108     .chart-message {
109         display: block;
110         margin-top: 10px;
111     }
112
113     #masthead h1 {
114         /*font-size: 30px;*/
115         line-height: 1;
116         padding-top: 30px;
117     }
118
119     #masthead .well {
120         margin-top:4%;
121     }
122
123     /* fix the navbar shifting when a modal is open */
124     /* https://github.com/twbs/bootstrap/issues/14040#issuecomment-159891033 */
125     body.modal-open{
126         width: 100% !important;
127         padding-right: 0 !important;
128 /*      overflow-y: scroll !important; */
129 /*      position: fixed !important;*/
130         overflow: visible;
131     }
132
133     /* make accordion use the whole header bar for expand/collapse */
134     .panel-title a {
135         display: block;
136         padding: 10px 15px;
137         margin: -10px -15px;
138     }
139
140     /*
141      * Side navigation
142      *
143      * Scrollspy and affixed enhanced navigation to highlight sections and secondary
144      * sections of docs content.
145      */
146
147     .affix {
148         position: static;
149         top: 70px !important;
150         /*width: 220px;*/
151     }
152
153     .affix-top {
154         /*width: 220px;*/
155     }
156
157     .dashboard-sidebar {
158         max-height: calc(100% - 70px) !important;
159         overflow-y: auto;
160         /*width: 220px !important;*/
161     }
162
163     /* By default it's not affixed in mobile views, so undo that */
164     .dashboard-sidebar.affix {
165         position: static;
166     }
167
168     @media (min-width: 768px) {
169         .dashboard-sidebar {
170             padding-left: 20px;
171         }
172     }
173
174     /* First level of nav */
175     .dashboard-sidenav {
176         margin-top: 20px;
177         margin-bottom: 20px;
178     }
179
180     /* All levels of nav */
181     .dashboard-sidebar .nav > li > a {
182         display: block;
183         padding: 4px 20px;
184         font-size: 13px;
185         font-weight: 500;
186         color: #767676;
187     }
188     .dashboard-sidebar .nav > li > a > .fa {
189         width: 20px;
190         text-align: center;
191     }
192     .dashboard-sidebar .nav > li > a:hover,
193     .dashboard-sidebar .nav > li > a:focus {
194         padding-left: 19px;
195         color: #563d7c;
196         text-decoration: none;
197         background-color: transparent;
198         border-left: 1px solid #563d7c;
199     }
200     .dashboard-sidebar .nav > .active > a,
201     .dashboard-sidebar .nav > .active:hover > a,
202     .dashboard-sidebar .nav > .active:focus > a {
203         padding-left: 18px;
204         font-weight: bold;
205         color: #563d7c;
206         background-color: transparent;
207         border-left: 2px solid #563d7c;
208     }
209
210     /* Nav: second level (shown on .active) */
211     .dashboard-sidebar .nav .nav {
212         display: none; /* Hide by default, but at >768px, show it */
213         padding-bottom: 10px;
214     }
215     .dashboard-sidebar .nav .nav > li > a {
216         padding-top: 1px;
217         padding-bottom: 1px;
218         padding-left: 30px;
219         font-size: 12px;
220         font-weight: normal;
221     }
222     .dashboard-sidebar .nav .nav > li > a:hover,
223     .dashboard-sidebar .nav .nav > li > a:focus {
224         padding-left: 29px;
225     }
226     .dashboard-sidebar .nav .nav > .active > a,
227     .dashboard-sidebar .nav .nav > .active:hover > a,
228     .dashboard-sidebar .nav .nav > .active:focus > a {
229         padding-left: 28px;
230         font-weight: 500;
231     }
232
233     .dropdown-menu {
234         min-width: 200px;
235     }
236     .dropdown-menu.columns-2 {
237         margin: 0;
238         padding: 0;
239         width: 400px;
240     }
241     .dropdown-menu li a {
242         padding: 5px 15px;
243         font-weight: 300;
244     }
245     .dropdown-menu.multi-column {
246         overflow-x: hidden;
247     }
248     .multi-column-dropdown {
249         list-style: none;
250         padding: 0;
251     }
252     .multi-column-dropdown li a {
253         display: block;
254         clear: both;
255         line-height: 1.428571429;
256         white-space: normal;
257     }
258     .multi-column-dropdown li a:hover {
259         text-decoration: none;
260         color: #f5f5f5;
261         background-color: #262626;
262     }
263     .scrollable-menu {
264         height: auto;
265         max-height: 80vh;
266         overflow-x: hidden;
267     }
268
269     /* Back to top (hidden on mobile) */
270     .back-to-top,
271     .dashboard-theme-toggle {
272         display: none;
273         padding: 4px 10px;
274         margin-top: 10px;
275         margin-left: 10px;
276         font-size: 12px;
277         font-weight: 500;
278         color: #999;
279     }
280     .back-to-top:hover,
281     .dashboard-theme-toggle:hover {
282         color: #563d7c;
283         text-decoration: none;
284     }
285     .dashboard-theme-toggle {
286         margin-top: 0;
287     }
288
289     .container {
290         width: calc(100% - 20px) !important;
291     }
292
293     .charts-body {
294         display: inline-block;
295         width: 100%;
296     }
297
298     .sidebar-body {
299         position: absolute;
300         display: none;
301     }
302
303     @media (min-width: 768px) {
304         .charts-body {
305             padding-left: 0%;
306             padding-right: 0%;
307         }
308
309         .back-to-top,
310         .dashboard-theme-toggle {
311             display: block;
312         }
313     }
314
315     /* Show and affix the side nav when space allows it */
316     @media (min-width: 992px) {
317         .container {
318             padding-left: 0% !important;
319         }
320
321         .charts-body {
322             width: calc(100% - 213px) !important;
323             padding-left: 1% !important;
324             padding-right: 0% !important;
325         }
326
327         .sidebar-body {
328             display: inline-block !important;
329             width: 213px !important;
330         }
331
332         .dashboard-sidebar .nav > .active > ul {
333             display: block;
334         }
335
336         /* Widen the fixed sidebar */
337         .dashboard-sidebar.affix,
338         .dashboard-sidebar.affix-top,
339         .dashboard-sidebar.affix-bottom {
340             width: 213px !important;
341         }
342         .dashboard-sidebar.affix {
343             position: fixed; /* Undo the static from mobile first approach */
344             top: 20px;
345         }
346         .dashboard-sidebar.affix-bottom {
347             position: absolute; /* Undo the static from mobile first approach */
348         }
349         .dashboard-sidebar.affix-bottom .dashboard-sidenav,
350         .dashboard-sidebar.affix .dashboard-sidenav {
351             margin-top: 0;
352             margin-bottom: 0;
353         }
354     }
355
356     @media (min-width: 1200px) {
357         .container {
358             padding-left: 2% !important;
359         }
360
361         .charts-body {
362             width: calc(100% - 233px) !important;
363             padding-left: 1% !important;
364             padding-right: 1% !important;
365         }
366
367         .sidebar-body {
368             display: inline-block !important;
369             width: 233px !important;
370         }
371
372         /* Widen the fixed sidebar again */
373         .dashboard-sidebar.affix,
374         .dashboard-sidebar.affix-top,
375         .dashboard-sidebar.affix-bottom {
376             width: 233px !important;
377         }
378     }
379
380     @media (min-width: 1360px) {
381         .container {
382             padding-left: 3% !important;
383         }
384
385         .charts-body {
386             width: calc(100% - 263px) !important;
387             padding-left: 1% !important;
388             padding-right: 2% !important;
389         }
390
391         .sidebar-body {
392             display: inline-block !important;
393             width: 263px !important;
394         }
395
396         /* Widen the fixed sidebar again */
397         .dashboard-sidebar.affix,
398         .dashboard-sidebar.affix-top,
399         .dashboard-sidebar.affix-bottom {
400             width: 263px !important;
401         }
402     }
403
404     </style>
405
406     <!-- check which theme to use -->
407     <script type="text/javascript">
408         // enable alarms checking and notifications
409         var netdataShowAlarms = true;
410
411         // enable registry updates
412         var netdataRegistry = true;
413
414         // --------------------------------------------------------------------
415         // urlOptions
416
417         var urlOptions = {
418             hash: '#',
419             theme: null,
420             help: null,
421             update_always: false,
422             pan_and_zoom: false,
423             after: 0,
424             before: 0,
425             nowelcome: false,
426             show_alarms: false,
427             chart: null,
428             family: null,
429             alarm: null,
430             alarm_unique_id: 0,
431             alarm_id: 0,
432             alarm_event_id: 0,
433
434             hasProperty: function(property) {
435                 // console.log('checking property ' + property + ' of type ' + typeof(this[property]));
436                 return typeof this[property] !== 'undefined';
437             },
438
439             genHash: function() {
440                 var hash = urlOptions.hash;
441
442                 if(urlOptions.pan_and_zoom === true) {
443                     hash += ';after='  + urlOptions.after.toString() +
444                             ';before=' + urlOptions.before.toString();
445                 }
446
447                 if(urlOptions.theme !== null)
448                     hash += ';theme=' + urlOptions.theme.toString();
449
450                 if(urlOptions.help !== null)
451                     hash += ';help=' + urlOptions.help.toString();
452
453                 if(urlOptions.update_always === true)
454                     hash += ';update_always=true';
455
456                 return hash;
457             },
458
459             parseHash: function() {
460                 var variables = document.location.hash.split(';');
461                 var len = variables.length;
462                 while(len--) {
463                     if(len !== 0) {
464                         var p = variables[len].split('=');
465                         if(urlOptions.hasProperty(p[0]) && typeof p[1] !== 'undefined')
466                             urlOptions[p[0]] = decodeURIComponent(p[1]);
467                     }
468                     else {
469                         if(variables[len].length > 0)
470                             urlOptions.hash = variables[len];
471                     }
472                 }
473
474                 var booleans = [ 'nowelcome', 'show_alarms', 'pan_and_zoom', 'update_always' ];
475                 len = booleans.length;
476                 while(len--) {
477                     if(urlOptions[booleans[len]] === 'true' || urlOptions[booleans[len]] === true || urlOptions[booleans[len]] === '1' || urlOptions[booleans[len]] === 1)
478                         urlOptions[booleans[len]] = true;
479                     else
480                         urlOptions[booleans[len]] = false;
481                 }
482
483                 if(urlOptions.before > 0 && urlOptions.after > 0) {
484                     urlOptions.pan_and_zoom = true;
485                     urlOptions.nowelcome = true;
486                 }
487                 else
488                     urlOptions.pan_and_zoom = false;
489
490                 // console.log(urlOptions);
491             },
492
493             hashUpdate: function() {
494                 history.replaceState(null, '', urlOptions.genHash());
495             },
496
497             netdataPanAndZoomCallback: function(status, after, before) {
498                 urlOptions.pan_and_zoom = status;
499                 urlOptions.after = after;
500                 urlOptions.before = before;
501                 urlOptions.hashUpdate();
502             }
503
504         };
505
506         urlOptions.parseHash();
507
508         // --------------------------------------------------------------------
509         // check options that should be processed before loading netdata.js
510
511         function loadLocalStorage(name) {
512             var ret = null;
513
514             try {
515                 if(typeof Storage !== "undefined" && typeof localStorage === 'object')
516                     ret = localStorage.getItem(name);
517             }
518             catch(error) {
519                 ;
520             }
521
522             if(typeof ret === 'undefined' || ret === null)
523                 return null;
524
525             // console.log('loaded: ' + name.toString() + ' = ' + ret.toString());
526
527             return ret;
528         }
529
530         function saveLocalStorage(name, value) {
531             // console.log('saving: ' + name.toString() + ' = ' + value.toString());
532             try {
533                 if(typeof Storage !== "undefined" && typeof localStorage === 'object') {
534                     localStorage.setItem(name, value.toString());
535                     return true;
536                 }
537             }
538             catch(error) {
539                 ;
540             }
541
542             return false;
543         }
544
545         function getTheme(def) {
546             var ret = loadLocalStorage('netdataTheme');
547             if(typeof ret === 'undefined' || ret === null || ret === 'undefined')
548                 return def;
549             else
550                 return ret;
551         }
552
553         function setTheme(theme) {
554             if(theme === netdataTheme) return false;
555             return saveLocalStorage('netdataTheme', theme);
556         }
557
558         var netdataTheme = getTheme('slate');
559         var netdataShowHelp = true;
560
561         if(urlOptions.theme !== null) {
562             setTheme(urlOptions.theme);
563             netdataTheme = urlOptions.theme;
564         }
565         else
566             urlOptions.theme = netdataTheme;
567
568         if(urlOptions.help !== null) {
569             saveLocalStorage('options.show_help', urlOptions.help);
570             netdataShowHelp = urlOptions.help;
571         }
572         else {
573             urlOptions.help = loadLocalStorage('options.show_help');
574         }
575
576         // --------------------------------------------------------------------
577         // registry call back to render my-netdata menu
578
579         var netdataRegistryCallback = function(machines_array) {
580             var el = '';
581             var a1 = '';
582             var found = 0;
583
584             if(machines_array === null) {
585                 var ret = loadLocalStorage("registryCallback");
586                 if(typeof ret !== 'undefined' && ret !== null) {
587                     machines_array = JSON.parse(ret);
588                     console.log("failed to contact the registry - loaded registry data from browser local storage");
589                 }
590             }
591
592             if(machines_array) {
593                 saveLocalStorage("registryCallback", JSON.stringify(machines_array));
594
595                 var machines = machines_array.sort(function (a, b) {
596                     if (a.name > b.name) return -1;
597                     if (a.name < b.name) return 1;
598                     return 0;
599                 });
600
601                 var len = machines.length;
602                 while(len--) {
603                     var u = machines[len];
604                     found++;
605                     el += '<li id="registry_server_' + u.guid + '"><a class="registry_link" href="' + u.url + '" onClick="return gotoServerModalHandler(\'' + u.guid + '\');">' + u.name + '</a></li>';
606                     a1 += '<li id="registry_action_' + u.guid + '"><a href="#" onclick="deleteRegistryModalHandler(\'' + u.guid + '\',\'' + u.name + '\',\'' + u.url + '\'); return false;"><i class="fa fa-trash-o" aria-hidden="true" style="color: #999;"></i></a></li>';
607                 }
608             }
609
610             if(!found) {
611                 if(machines)
612                     el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #666;" target="_blank">your netdata server list is empty...</a></li>';
613                 else
614                     el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #666;" target="_blank">failed to contact the registry...</a></li>';
615
616                 a1 += '<li><a href="#" onClick="return false;">&nbsp;</a></li>';
617
618                 el += '<li role="separator" class="divider"></li>' +
619                         '<li><a href="//london.netdata.rocks/default.html">UK - London (DigitalOcean.com)</a></li>' +
620                         '<li><a href="//newyork.netdata.rocks/default.html">US - New York (DigitalOcean.com)</a></li>' +
621                         '<li><a href="//sanfrancisco.netdata.rocks/default.html">US - San Francisco (DigitalOcean.com)</a></li>' +
622                         '<li><a href="//atlanta.netdata.rocks/default.html">US - Atlanta (CDN77.com)</a></li>' +
623                         '<li><a href="//frankfurt.netdata.rocks/default.html">Germany - Frankfurt (DigitalOcean.com)</a></li>' +
624                         '<li><a href="//toronto.netdata.rocks/default.html">Canada - Toronto (DigitalOcean.com)</a></li>' +
625                         '<li><a href="//singapore.netdata.rocks/default.html">Japan - Singapore (DigitalOcean.com)</a></li>' +
626                         '<li><a href="//bangalore.netdata.rocks/default.html">India - Bangalore (DigitalOcean.com)</a></li>';
627                 a1 += '<li role="separator" class="divider"></li>' +
628                         '<li><a href="#">&nbsp;</a></li>' +
629                         '<li><a href="#">&nbsp;</a></li>'+
630                         '<li><a href="#">&nbsp;</a></li>'+
631                         '<li><a href="#">&nbsp;</a></li>'+
632                         '<li><a href="#">&nbsp;</a></li>'+
633                         '<li><a href="#">&nbsp;</a></li>'+
634                         '<li><a href="#">&nbsp;</a></li>'+
635                         '<li><a href="#">&nbsp;</a></li>';
636             }
637
638             el += '<li role="separator" class="divider"></li>';
639             a1 += '<li role="separator" class="divider"></li>';
640
641             el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #999;" target="_blank">What is this?</a></li>';
642             a1 += '<li><a href="#" style="color: #999;" onclick="switchRegistryModalHandler(); return false;"><i class="fa fa-sliders" aria-hidden="true" style="color: #999;"></i></a></li>'
643
644             document.getElementById('mynetdata_servers').innerHTML = el;
645             document.getElementById('mynetdata_servers2').innerHTML = el;
646             document.getElementById('mynetdata_actions1').innerHTML = a1;
647
648             gotoServerInit();
649         };
650
651         var this_is_demo = null; // FIXME
652         function isdemo() {
653             if(this_is_demo !== null) return this_is_demo;
654             this_is_demo = false;
655
656             try {
657                 if(typeof document.location.hostname === 'string') {
658                     if(document.location.hostname.endsWith('.my-netdata.io') ||
659                             document.location.hostname.endsWith('.mynetdata.io') ||
660                             document.location.hostname.endsWith('.netdata.rocks') ||
661                             document.location.hostname.endsWith('.firehol.org') ||
662                             document.location.hostname.endsWith('.netdata.online'))
663                             this_is_demo = true;
664                 }
665             }
666             catch(error) {
667                 ;
668             }
669
670             return this_is_demo;
671         }
672
673         function netdataURL(url) {
674             if(typeof url === 'undefined')
675                 url = document.location.toString();
676
677             if(url.indexOf('#') !== -1)
678                 url = url.substring(0, url.indexOf('#'));
679
680             var hash = urlOptions.genHash();
681
682             // console.log('netdataURL: ' + url + hash);
683
684             return url + hash;
685         }
686
687         function netdataReload(url) {
688             var t = netdataURL(url);
689             // console.log('netdataReload: ' + t);
690             document.location = t;
691
692             // since we play with hash
693             // this is needed to reload the page
694             location.reload();
695         }
696
697         var gotoServerValidateRemaining = 0;
698         var gotoServerMiddleClick = false;
699         var gotoServerStop = false;
700         function gotoServerValidateUrl(id, guid, url) {
701             var penaldy = 0;
702             var error = 'failed';
703
704             if(document.location.toString().startsWith('http://') && url.toString().startsWith('https://'))
705                 // we penalize https only if the current url is http
706                 // to allow the user walk through all its servers.
707                 penaldy = 500;
708
709             else if(document.location.toString().startsWith('https://') && url.toString().startsWith('http://'))
710                 error = 'can\'t check';
711
712             var finalURL = netdataURL(url);
713
714             setTimeout(function() {
715                 document.getElementById('gotoServerList').innerHTML += '<tr><td style="padding-left: 20px;"><a href="' + finalURL + '" target="_blank">' + url + '</a></td><td style="padding-left: 30px;"><code id="' + guid + '-' + id + '-status">checking...</code></td></tr>';
716
717                 NETDATA.registry.hello(url, function(data) {
718                     if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid === guid) {
719                         // console.log('OK ' + id + ' URL: ' + url);
720                         document.getElementById(guid + '-' + id + '-status').innerHTML = "OK";
721
722                         if(!gotoServerStop) {
723                             gotoServerStop = true;
724
725                             if(gotoServerMiddleClick) {
726                                 window.open(finalURL, '_blank');
727                                 gotoServerMiddleClick = false;
728                                 document.getElementById('gotoServerResponse').innerHTML = '<b>Opening new window to ' + NETDATA.registry.machines[guid].name + '<br/><a href="' + finalURL + '">' + url + '</a></b><br/>(check your pop-up blocker if it fails)';
729                             }
730                             else {
731                                 document.getElementById('gotoServerResponse').innerHTML += 'found it! It is at:<br/><small>' + url + '</small>';
732                                 document.location = finalURL;
733                             }
734                         }
735                     }
736                     else {
737                         if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid !== guid)
738                             error = 'wrong machine';
739
740                         document.getElementById(guid + '-' + id + '-status').innerHTML = error;
741                         gotoServerValidateRemaining--;
742                         if(gotoServerValidateRemaining <= 0) {
743                             gotoServerMiddleClick = false;
744                             document.getElementById('gotoServerResponse').innerHTML = '<b>Sorry! I cannot find any operational URL for this server</b>';
745                         }
746                     }
747                 });
748             }, (id * 50) + penaldy);
749         }
750
751         function gotoServerModalHandler(guid) {
752             // console.log('goto server: ' + guid);
753
754             gotoServerStop = false;
755             var checked = {};
756             var len = NETDATA.registry.machines[guid].alternate_urls.length;
757             var count = 0;
758
759             document.getElementById('gotoServerResponse').innerHTML = '';
760             document.getElementById('gotoServerList').innerHTML = '';
761             document.getElementById('gotoServerName').innerHTML = NETDATA.registry.machines[guid].name;
762             $('#gotoServerModal').modal('show');
763
764             gotoServerValidateRemaining = len;
765             while(len--) {
766                 var url = NETDATA.registry.machines[guid].alternate_urls[len];
767                 checked[url] = true;
768                 gotoServerValidateUrl(count++, guid, url);
769             }
770
771             setTimeout(function() {
772                 if(gotoServerStop === false) {
773                     document.getElementById('gotoServerResponse').innerHTML = '<b>Added all the known URLs for this machine.</b>';
774                     NETDATA.registry.search(guid, function(data) {
775                         // console.log(data);
776                         len = data.urls.length;
777                         while(len--) {
778                             var url = data.urls[len][1];
779                             // console.log(url);
780                             if(typeof checked[url] === 'undefined') {
781                                 gotoServerValidateRemaining++;
782                                 checked[url] = true;
783                                 gotoServerValidateUrl(count++, guid, url);
784                             }
785                         }
786                     });
787                 }
788             }, 2000);
789             return false;
790         }
791
792         function gotoServerInit() {
793             $(".registry_link").on('click', function(e) {
794                 if(e.which === 2) {
795                     e.preventDefault();
796                     gotoServerMiddleClick = true;
797                 }
798                 else {
799                     gotoServerMiddleClick = false;
800                 }
801
802                 return true;
803             });
804         }
805
806         function switchRegistryModalHandler() {
807             document.getElementById('switchRegistryPersonGUID').value = NETDATA.registry.person_guid;
808             document.getElementById('switchRegistryURL').innerHTML = NETDATA.registry.server;
809             document.getElementById('switchRegistryResponse').innerHTML = '';
810             $('#switchRegistryModal').modal('show');
811         }
812
813         function notifyForSwitchRegistry() {
814             var n = document.getElementById('switchRegistryPersonGUID').value;
815
816             if(n !== '' && n.length === 36) {
817                 NETDATA.registry.switch(n, function(result) {
818                     if(result !== null) {
819                         $('#switchRegistryModal').modal('hide');
820                         NETDATA.registry.init();
821                     }
822                     else {
823                         document.getElementById('switchRegistryResponse').innerHTML = "<b>Sorry! The registry rejected your request.</b>";
824                     }
825                 });
826             }
827             else
828                 document.getElementById('switchRegistryResponse').innerHTML = "<b>The ID you have entered is not a GUID.</b>";
829         }
830
831         var deleteRegistryUrl = null;
832         function deleteRegistryModalHandler(guid, name, url) {
833             deleteRegistryUrl = url;
834             document.getElementById('deleteRegistryServerName').innerHTML = name;
835             document.getElementById('deleteRegistryServerName2').innerHTML = name;
836             document.getElementById('deleteRegistryServerURL').innerHTML = url;
837             document.getElementById('deleteRegistryResponse').innerHTML = '';
838             $('#deleteRegistryModal').modal('show');
839         }
840
841         function notifyForDeleteRegistry() {
842             if(deleteRegistryUrl) {
843                 NETDATA.registry.delete(deleteRegistryUrl, function(result) {
844                     if(result !== null) {
845                         deleteRegistryUrl = null;
846                         $('#deleteRegistryModal').modal('hide');
847                         NETDATA.registry.init();
848                     }
849                     else {
850                         document.getElementById('deleteRegistryResponse').innerHTML = "<b>Sorry! this command was rejected by the registry server.</b>";
851                     }
852                 });
853             }
854         }
855
856         var options = {
857             sparklines_registry: {},
858             menus: {},
859             submenu_names: {},
860             data: null,
861             hostname: 'netdata_server', // will be overwritten by the netdata server
862             categories: new Array(),
863             categories_idx: {},
864             families: new Array(),
865             families_idx: {},
866
867             chartsPerRow: 0,
868             chartsMinWidth: 1450,
869             chartsHeight: 180,
870             sparklinesHeight: 60,
871         };
872
873         // generate a sparkline
874         // used in the documentation
875         function sparkline(chart, dimension, units) {
876             var key = chart + '.' + dimension;
877
878             if(typeof units === 'undefined')
879                 units = '';
880
881             if(typeof options.sparklines_registry[key] === 'undefined')
882                 options.sparklines_registry[key] = { count: 1 };
883             else
884                 options.sparklines_registry[key].count++;
885
886             key = key + '.' + options.sparklines_registry[key].count;
887
888             var h = '<div data-netdata="' + chart + '" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dimensions="' + dimension + '" data-show-value-of-' + dimension + '-at="' + key + '"></div> (<span id="' + key + '" style="display: inline-block; min-width: 50px; text-align: right;">X</span>' + units + ')';
889
890             return h;
891         }
892
893         function chartsPerRow(total) {
894             if(options.chartsPerRow === 0) {
895                 width = Math.floor(total / options.chartsMinWidth);
896                 if(width === 0) width = 1;
897                 return width;
898             }
899             else return options.chartsPerRow;
900         }
901
902         function prioritySort(a, b) {
903             if(a.priority < b.priority) return -1;
904             if(a.priority > b.priority) return 1;
905             if(a.name < b.name) return -1;
906             return 1;
907         }
908
909         function sortObjectByPriority(object) {
910             var idx = {};
911             var sorted = new Array();
912
913             for(var i in object) {
914                 if(typeof idx[i] === 'undefined') {
915                     idx[i] = object[i];
916                     sorted.push(i);
917                 }
918             }
919
920             sorted.sort(function(a, b) {
921                 if(idx[a].priority < idx[b].priority) return -1;
922                 if(idx[a].priority > idx[b].priority) return 1;
923                 if(a < b) return -1;
924                 return 1;
925             });
926
927             return sorted;
928         }
929
930
931         // ----------------------------------------------------------------------------
932         // scroll to a section, without changing the browser history
933
934         function scrollToId(hash) {
935             if(hash && hash != '' && document.getElementById(hash) !== null) {
936                 var offset = $('#' + hash).offset();
937                 if(typeof offset !== 'undefined')
938                     $('html, body').animate({ scrollTop: offset.top }, 0);
939             }
940
941             // we must return false to prevent the default action
942             return false;
943         }
944
945         // ----------------------------------------------------------------------------
946
947         var netdataDashboard = {
948             menu: {},
949             submenu: {},
950             context: {},
951
952             gaugeChart: function(title, width, dimensions, colors) {
953                 if(typeof colors === 'undefined')
954                     colors = '';
955
956                 if(typeof dimensions === 'undefined')
957                     dimensions = '';
958
959                 return '<div data-netdata="CHART_UNIQUE_ID"'
960                                         + ' data-dimensions="' + dimensions + '"'
961                                         + ' data-chart-library="gauge"'
962                                         + ' data-gauge-adjust="width"'
963                                         + ' data-title="' + title + '"'
964                                         + ' data-width="' + width + '"'
965                                         + ' data-before="0"'
966                                         + ' data-after="-CHART_DURATION"'
967                                         + ' data-points="CHART_DURATION"'
968                                         + ' data-colors="' + colors + '"'
969                                         + ' role="application"></div>';
970             },
971
972             anyAttribute: function(obj, attr, key, def) {
973                 if(typeof obj[key] !== 'undefined') {
974                     if(typeof obj[key][attr] !== 'undefined')
975                         return obj[key][attr];
976                 }
977                 return def;
978             },
979
980             menuTitle: function(chart) {
981                 if(typeof chart.menu_pattern !== 'undefined') {
982                     return (netdataDashboard.anyAttribute(netdataDashboard.menu, 'title', chart.menu_pattern, chart.menu_pattern).toString()
983                             + '&nbsp;' + chart.type.slice(-(chart.type.length - chart.menu_pattern.length - 1)).toString()).replace(/_/g, ' ');
984                 }
985
986                 return (netdataDashboard.anyAttribute(netdataDashboard.menu, 'title', chart.menu, chart.menu)).toString().replace(/_/g, ' ');
987             },
988
989             menuIcon: function(chart) {
990                 if(typeof chart.menu_pattern !== 'undefined')
991                     return netdataDashboard.anyAttribute(netdataDashboard.menu, 'icon', chart.menu_pattern, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>').toString();
992
993                 return netdataDashboard.anyAttribute(netdataDashboard.menu, 'icon', chart.menu, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>');
994             },
995
996             menuInfo: function(menu) {
997                 return netdataDashboard.anyAttribute(netdataDashboard.menu, 'info', menu, null);
998             },
999
1000             menuHeight: function(menu, relative) {
1001                 return netdataDashboard.anyAttribute(netdataDashboard.menu, 'height', menu, 1.0) * relative;
1002             },
1003
1004             submenuTitle: function(menu, submenu) {
1005                 var key = menu + '.' + submenu;
1006                 var title = netdataDashboard.anyAttribute(netdataDashboard.submenu, 'title', key, submenu).toString().replace(/_/g, ' ');;
1007                 if(title.length > 28) {
1008                     var a = title.substring(0, 13);
1009                     var b = title.substring(title.length - 12, title.length);
1010                     return a + '...' + b;
1011                 }
1012                 return title;
1013             },
1014
1015             submenuInfo: function(menu, submenu) {
1016                 var key = menu + '.' + submenu;
1017                 return netdataDashboard.anyAttribute(netdataDashboard.submenu, 'info', key, null);
1018             },
1019
1020             submenuHeight: function(menu, submenu, relative) {
1021                 var key = menu + '.' + submenu;
1022                 return netdataDashboard.anyAttribute(netdataDashboard.submenu, 'height', key, 1.0) * relative;
1023             },
1024
1025             contextInfo: function(id) {
1026                 if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].info !== 'undefined')
1027                     return '<div class="chart-message netdata-chart-alignment" role="document">' + netdataDashboard.context[id].info + '</div>';
1028                 else
1029                     return '';
1030             },
1031
1032             contextValueRange: function(id) {
1033                 if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].valueRange !== 'undefined')
1034                     return netdataDashboard.context[id].valueRange;
1035                 else
1036                     return '[null, null]';
1037             },
1038
1039             contextHeight: function(id, def) {
1040                 if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].height !== 'undefined')
1041                     return def * netdataDashboard.context[id].height;
1042                 else
1043                     return def;
1044             }
1045         };
1046
1047         // ----------------------------------------------------------------------------
1048
1049         // enrich the data structure returned by netdata
1050         // to reflect our menu system and content
1051         function enrichChartData(chart) {
1052             var tmp = chart.type.split('_')[0];
1053
1054             switch(tmp) {
1055                 case 'ap':
1056                 case 'net':
1057                 case 'disk':
1058                     chart.menu = tmp;
1059                     break;
1060
1061                 case 'cgroup':
1062                     chart.menu = chart.type;
1063                     if(chart.id.match(/.*[\._\/-:]qemu[\._\/-:]*/) || chart.id.match(/.*[\._\/-:]kvm[\._\/-:]*/))
1064                         chart.menu_pattern = 'cgqemu';
1065                     else
1066                         chart.menu_pattern = 'cgroup';
1067                     break;
1068
1069                 case 'apache':
1070                 case 'exim':
1071                 case 'dovecot':
1072                 case 'hddtemp':
1073                 case 'ipfs':
1074                 case 'memcached':
1075                 case 'mysql':
1076                 case 'named':
1077                 case 'nginx':
1078                 case 'nut':
1079                 case 'phpfpm':
1080                 case 'postfix':
1081                 case 'postgres':
1082                 case 'redis':
1083                 case 'retroshare':
1084                 case 'smawebbox':
1085                 case 'snmp':
1086                 case 'squid':
1087                 case 'tomcat':
1088                     chart.menu = chart.type;
1089                     chart.menu_pattern = tmp;
1090                     break;
1091
1092                 case 'tc':
1093                     chart.menu = tmp;
1094
1095                     // find a name for this device from fireqos info
1096                     // we strip '_(in|out)' or '(in|out)_'
1097                     if(typeof options.submenu_names[chart.family] === 'undefined' || options.submenu_names[chart.family] === chart.family) {
1098                         var n = chart.name.split('.')[1];
1099                         if(n.endsWith('_in'))
1100                             options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_in'));
1101                         else if(n.endsWith('_out'))
1102                             options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_out'));
1103                         else if(n.startsWith('in_'))
1104                             options.submenu_names[chart.family] = n.slice(3, n.length);
1105                         else if(n.startsWith('out_'))
1106                             options.submenu_names[chart.family] = n.slice(4, n.length);
1107                     }
1108
1109                     // increase the priority of IFB devices
1110                     // to have inbound appear before outbound
1111                     if(chart.id.match(/.*-ifb$/))
1112                         chart.priority--;
1113
1114                     break;
1115
1116                 default:
1117                     chart.menu = chart.type;
1118                     break;
1119             }
1120
1121             chart.submenu = chart.family;
1122         }
1123
1124         // ----------------------------------------------------------------------------
1125
1126         function headMain(charts, duration) {
1127             var head = '';
1128
1129             if(typeof charts['system.swap'] !== 'undefined')
1130                 head += '<div style="margin-right: 10px;" data-netdata="system.swap"'
1131                 + ' data-dimensions="used"'
1132                 + ' data-append-options="percentage"'
1133                 + ' data-chart-library="easypiechart"'
1134                 + ' data-title="Used Swap"'
1135                 + ' data-units="%"'
1136                 + ' data-easypiechart-max-value="100"'
1137                 + ' data-width="8%"'
1138                 + ' data-before="0"'
1139                 + ' data-after="-' + duration.toString() + '"'
1140                 + ' data-points="' + duration.toString() + '"'
1141                 + ' data-colors="#DD4400"'
1142                 + ' role="application"></div>';
1143
1144             if(typeof charts['system.io'] !== 'undefined') {
1145                 head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1146                 + ' data-dimensions="in"'
1147                 + ' data-chart-library="easypiechart"'
1148                 + ' data-title="Disk Read"'
1149                 + ' data-width="10%"'
1150                 + ' data-before="0"'
1151                 + ' data-after="-' + duration.toString() + '"'
1152                 + ' data-points="' + duration.toString() + '"'
1153                 + ' role="application"></div>';
1154
1155                 head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1156                 + ' data-dimensions="out"'
1157                 + ' data-chart-library="easypiechart"'
1158                 + ' data-title="Disk Write"'
1159                 + ' data-width="10%"'
1160                 + ' data-before="0"'
1161                 + ' data-after="-' + duration.toString() + '"'
1162                 + ' data-points="' + duration.toString() + '"'
1163                 + ' role="application"></div>';
1164             }
1165
1166             if(typeof charts['system.cpu'] !== 'undefined')
1167                 head += '<div data-netdata="system.cpu"'
1168                 + ' data-chart-library="gauge"'
1169                 + ' data-title="CPU"'
1170                 + ' data-units="%"'
1171                 + ' data-gauge-max-value="100"'
1172                 + ' data-width="18%"'
1173                 + ' data-after="-' + duration.toString() + '"'
1174                 + ' data-points="' + duration.toString() + '"'
1175                 + ' data-colors="' + NETDATA.colors[12] + '"'
1176                 + ' role="application"></div>';
1177
1178             if(typeof charts['system.ipv4'] !== 'undefined') {
1179                 head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1180                 + ' data-dimensions="received"'
1181                 + ' data-chart-library="easypiechart"'
1182                 + ' data-title="IPv4 Inbound"'
1183                 + ' data-width="10%"'
1184                 + ' data-before="0"'
1185                 + ' data-after="-' + duration.toString() + '"'
1186                 + ' data-points="' + duration.toString() + '"'
1187                 + ' role="application"></div>';
1188
1189                 head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1190                 + ' data-dimensions="sent"'
1191                 + ' data-chart-library="easypiechart"'
1192                 + ' data-title="IPv4 Outbound"'
1193                 + ' data-width="10%"'
1194                 + ' data-before="0"'
1195                 + ' data-after="-' + duration.toString() + '"'
1196                 + ' data-points="' + duration.toString() + '"'
1197                 + ' role="application"></div>';
1198             }
1199             else if(typeof charts['system.ipv6'] !== 'undefined') {
1200                 head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"'
1201                 + ' data-dimensions="received"'
1202                 + ' data-chart-library="easypiechart"'
1203                 + ' data-title="IPv6 Inbound"'
1204                 + ' data-units="kbps"'
1205                 + ' data-width="10%"'
1206                 + ' data-before="0"'
1207                 + ' data-after="-' + duration.toString() + '"'
1208                 + ' data-points="' + duration.toString() + '"'
1209                 + ' role="application"></div>';
1210
1211                 head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"'
1212                 + ' data-dimensions="sent"'
1213                 + ' data-chart-library="easypiechart"'
1214                 + ' data-title="IPv6 Outbound"'
1215                 + ' data-units="kbps"'
1216                 + ' data-width="10%"'
1217                 + ' data-before="0"'
1218                 + ' data-after="-' + duration.toString() + '"'
1219                 + ' data-points="' + duration.toString() + '"'
1220                 + ' role="application"></div>';
1221             }
1222
1223             if(typeof charts['system.ram'] !== 'undefined')
1224                 head += '<div style="margin-right: 10px;" data-netdata="system.ram"'
1225                 + ' data-dimensions="used|buffers|active|wired"' // active and wired are FreeBSD stats
1226                 + ' data-append-options="percentage"'
1227                 + ' data-chart-library="easypiechart"'
1228                 + ' data-title="Used RAM"'
1229                 + ' data-units="%"'
1230                 + ' data-easypiechart-max-value="100"'
1231                 + ' data-width="8%"'
1232                 + ' data-after="-' + duration.toString() + '"'
1233                 + ' data-points="' + duration.toString() + '"'
1234                 + ' data-colors="' + NETDATA.colors[7] + '"'
1235                 + ' role="application"></div>';
1236
1237             return head;
1238         }
1239
1240         function generateHeadCharts(type, chart, duration) {
1241             var head = '';
1242             var hcharts = netdataDashboard.anyAttribute(netdataDashboard.context, type, chart.context, []);
1243             if(hcharts.length > 0) {
1244                 var hi = 0, hlen = hcharts.length;
1245                 while(hi < hlen) {
1246                     if(typeof hcharts[hi] === 'function')
1247                         head += hcharts[hi](chart.id).replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id);
1248                     else
1249                         head += hcharts[hi].replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id);
1250                     hi++;
1251                 }
1252             }
1253             return head;
1254         }
1255
1256         function renderPage(menus, data) {
1257             var div = document.getElementById('charts_div');
1258             var pcent_width = Math.floor(100 / chartsPerRow($(div).width()));
1259
1260             // find the proper duration for per-second updates
1261             var duration = Math.round(($(div).width() * pcent_width / 100 * data.update_every / 3) / 60) * 60;
1262             var html = '';
1263             var sidebar = '<ul class="nav dashboard-sidenav" data-spy="affix" id="sidebar_ul">';
1264             var mainhead = headMain(data.charts, duration);
1265
1266             // sort the menus
1267             var main = sortObjectByPriority(menus);
1268             var i = 0, len = main.length;
1269             while(i < len) {
1270                 var menu = main[i++];
1271
1272                 // generate an entry at the main menu
1273
1274                 var menuid = NETDATA.name2id('menu_' + menu);
1275                 sidebar += '<li class=""><a href="#' + menuid + '" onClick="return scrollToId(\'' + menuid + '\');">' + menus[menu].icon + ' ' + menus[menu].title + '</a><ul class="nav">';
1276                 html += '<div role="section"><div role="sectionhead"><h1 id="' + menuid + '" role="heading">' + menus[menu].title + '</h1></div><div role="document">';
1277
1278                 if(menus[menu].info !== null)
1279                     html += menus[menu].info;
1280
1281                 // console.log(' >> ' + menu + ' (' + menus[menu].priority + '): ' + menus[menu].title);
1282
1283                 var shtml = '';
1284                 var mhead = '<div class="netdata-chart-row">' + mainhead;
1285                 mainhead = '';
1286
1287                 // sort the submenus of this menu
1288                 var sub = sortObjectByPriority(menus[menu].submenus);
1289                 var si = 0, slen = sub.length;
1290                 while(si < slen) {
1291                     var submenu = sub[si++];
1292
1293                     // generate an entry at the submenu
1294                     var submenuid = NETDATA.name2id('menu_' + menu + '_submenu_' + submenu);
1295                     sidebar += '<li class><a href="#' + submenuid + '" onClick="return scrollToId(\'' + submenuid + '\');">' + menus[menu].submenus[submenu].title + '</a></li>';
1296                     shtml += '<div class="netdata-group-container" id="' + submenuid + '" style="display: inline-block; width: ' + pcent_width.toString() + '%"><h2 id="' + submenuid + '" class="netdata-chart-alignment" role="heading">' + menus[menu].submenus[submenu].title + '</h2>';
1297
1298                     if(menus[menu].submenus[submenu].info !== null)
1299                         shtml += '<div class="chart-message netdata-chart-alignment" role="document">' + menus[menu].submenus[submenu].info + '</div>';
1300
1301                     var head = '<div class="netdata-chart-row">';
1302                     var chtml = '';
1303
1304                     // console.log('    \------- ' + submenu + ' (' + menus[menu].submenus[submenu].priority + '): ' + menus[menu].submenus[submenu].title);
1305
1306                     // sort the charts in this submenu of this menu
1307                     menus[menu].submenus[submenu].charts.sort(prioritySort);
1308                     var ci = 0, clen = menus[menu].submenus[submenu].charts.length;
1309                     while(ci < clen) {
1310                         var chart = menus[menu].submenus[submenu].charts[ci++];
1311
1312                         // generate the submenu heading charts
1313                         mhead += generateHeadCharts('mainheads', chart, duration);
1314                         head += generateHeadCharts('heads', chart, duration);
1315
1316                         // generate the chart
1317                         chtml += netdataDashboard.contextInfo(chart.context) + '<div id="chart_' + NETDATA.name2id(chart.id) + '" data-netdata="' + chart.id + '"'
1318                             + ' data-width="' + pcent_width.toString() + '%"'
1319                             + ' data-height="' + netdataDashboard.contextHeight(chart.context, options.chartsHeight).toString() + 'px"'
1320                             + ' data-dygraph-valuerange="' + netdataDashboard.contextValueRange(chart.context) + '"'
1321                             + ' data-before="0"'
1322                             + ' data-after="-' + duration.toString() + '"'
1323                             + ' data-id="' + NETDATA.name2id(options.hostname + '/' + chart.id) + '"'
1324                             + ' data-colors="' + netdataDashboard.anyAttribute(netdataDashboard.context, 'colors', chart.context, '') + '"'
1325                             + ' role="application"></div>';
1326
1327                         // console.log('         \------- ' + chart.id + ' (' + chart.priority + '): ' + chart.context  + ' height: ' + menus[menu].submenus[submenu].height);
1328                     }
1329
1330                     head += '</div>';
1331                     shtml += head + chtml + '</div>';
1332                 }
1333
1334                 mhead += '</div>';
1335                 sidebar += '</ul></li>';
1336                 html += mhead + shtml + '</div></div><hr role="separator"/>';
1337             }
1338
1339             sidebar += '<li class="" style="padding-top:15px;"><a href="https://github.com/firehol/netdata/wiki/Add-more-charts-to-netdata" target="_blank"><i class="fa fa-plus" aria-hidden="true"></i> add more charts</a></li>';
1340             sidebar += '<li class=""><a href="https://github.com/firehol/netdata/wiki/Add-more-alarms-to-netdata" target="_blank"><i class="fa fa-plus" aria-hidden="true"></i> add more alarms</a></li>';
1341             sidebar += '<li class="" style="margin:20px;color:#666;"><small>netdata on <b>' + data.hostname.toString() + '</b>, collects every ' + ((data.update_every == 1)?'second':data.update_every.toString() + ' seconds') + ' <b>' + data.dimensions_count.toLocaleString() + '</b> metrics, presented as <b>' + data.charts_count.toLocaleString() + '</b> charts and monitored by <b>' + data.alarms_count.toLocaleString() + '</b> alarms, using ' + Math.round(data.rrd_memory_bytes / 1024 / 1024).toLocaleString() + ' MB of memory for ' + Math.round(data.history / (3600/data.update_every)).toLocaleString() + ' ' + ((data.history == (3600/data.update_every))?'hour':'hours').toString() + ' of real-time history.</small></li>';
1342             sidebar += '</ul>';
1343             div.innerHTML = html;
1344             document.getElementById('sidebar').innerHTML = sidebar;
1345             finalizePage();
1346         }
1347
1348         function renderChartsAndMenu(data) {
1349             var menus = options.menus;
1350             var charts = data.charts;
1351
1352             for(var c in charts) {
1353                 enrichChartData(charts[c]);
1354
1355                 // create the menu
1356                 if(typeof menus[charts[c].menu] === 'undefined') {
1357                     menus[charts[c].menu] = {
1358                         priority: charts[c].priority,
1359                         submenus: {},
1360                         title: netdataDashboard.menuTitle(charts[c]),
1361                         icon: netdataDashboard.menuIcon(charts[c]),
1362                         info: netdataDashboard.menuInfo(charts[c].menu),
1363                         height: netdataDashboard.menuHeight(charts[c].menu, options.chartsHeight)
1364                     };
1365                 }
1366
1367                 if(charts[c].priority < menus[charts[c].menu].priority)
1368                     menus[charts[c].menu].priority = charts[c].priority;
1369
1370                 // create the submenu
1371                 if(typeof menus[charts[c].menu].submenus[charts[c].submenu] === 'undefined') {
1372                     menus[charts[c].menu].submenus[charts[c].submenu] = {
1373                         priority: charts[c].priority,
1374                         charts: new Array(),
1375                         title: null,
1376                         info: netdataDashboard.submenuInfo(charts[c].menu, charts[c].submenu),
1377                         height: netdataDashboard.submenuHeight(charts[c].menu, charts[c].submenu, menus[charts[c].menu].height)
1378                     };
1379                 }
1380
1381                 if(charts[c].priority < menus[charts[c].menu].submenus[charts[c].submenu].priority)
1382                     menus[charts[c].menu].submenus[charts[c].submenu].priority = charts[c].priority;
1383
1384                 // index the chart in the menu/submenu
1385                 menus[charts[c].menu].submenus[charts[c].submenu].charts.push(charts[c]);
1386             }
1387
1388             // propagate the descriptive subname given to QoS
1389             // to all the other submenus with the same name
1390             for(var m in menus) {
1391                 for(var s in menus[m].submenus) {
1392                     // set the family using a name
1393                     if(typeof options.submenu_names[s] !== 'undefined') {
1394                         menus[m].submenus[s].title = s + ' (' + options.submenu_names[s] + ')';
1395                     }
1396                     else {
1397                         menus[m].submenus[s].title = netdataDashboard.submenuTitle(m, s);
1398                     }
1399                 }
1400             }
1401
1402             renderPage(menus, data);
1403         }
1404
1405         // ----------------------------------------------------------------------------
1406
1407         function loadJs(url, callback) {
1408             $.ajax({
1409                 url: url,
1410                 cache: true,
1411                 dataType: "script",
1412                 xhrFields: { withCredentials: true } // required for the cookie
1413             })
1414             .fail(function() {
1415                 alert('Cannot load required JS library: ' + url);
1416             })
1417             .always(function() {
1418                 if(typeof callback === 'function')
1419                     callback();
1420             })
1421         }
1422
1423         var bootstrapTableLoaded = false;
1424         function loadBootstrapTable(callback) {
1425             if(bootstrapTableLoaded === false) {
1426                 bootstrapTableLoaded === true;
1427                 loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-1.11.0.min.js', function() {
1428                     loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-export-1.11.0.min.js', function() {
1429                         loadJs(NETDATA.serverDefault + 'lib/tableExport-1.6.0.min.js', callback);
1430                     })
1431                 });
1432             }
1433             else callback();
1434         }
1435
1436         function alarmsUpdateModal() {
1437             var active = '<h3>Raised Alarms</h3><table class="table">';
1438             var all = '<h3>All Running Alarms</h3><div class="panel-group" id="alarms_all_accordion" role="tablist" aria-multiselectable="true">';
1439             var footer = '<hr/><a href="https://github.com/firehol/netdata/wiki/Generating-Badges" target="_blank">netdata badges</a> refresh automatically. Their color indicates the state of the alarm: <span style="color: #e05d44"><b>&nbsp;red&nbsp;</b></span> is critical, <span style="color:#fe7d37"><b>&nbsp;orange&nbsp;</b></span> is warning, <span style="color: #4c1"><b>&nbsp;bright green&nbsp;</b></span> is ok, <span style="color: #9f9f9f"><b>&nbsp;light grey&nbsp;</b></span> is undefined (i.e. no data or no status), <span style="color: #000"><b>&nbsp;black&nbsp;</b></span> is not initialized. You can copy and paste their URLs to embed them in any web page.<br/>netdata can send notifications for these alarms. Check <a href="https://github.com/firehol/netdata/blob/master/conf.d/health_alarm_notify.conf">this configuration file</a> for more information.';
1440
1441             NETDATA.alarms.get('all', function(data) {
1442                 options.alarm_families = new Array();
1443
1444                 alarmsCallback(data);
1445
1446                 if(data === null) {
1447                     document.getElementById('alarms_active').innerHTML =
1448                             document.getElementById('alarms_all').innerHTML =
1449                                     document.getElementById('alarms_log').innerHTML =
1450                                             'failed to load alarm data!';
1451                     return;
1452                 }
1453
1454                 function alarmid4human(id) {
1455                     if(id === 0)
1456                         return '-';
1457
1458                     return id.toString();
1459                 }
1460
1461                 function timestamp4human(timestamp, space) {
1462                     if(timestamp === 0)
1463                         return '-';
1464
1465                     if(typeof space === 'undefined')
1466                         space = '&nbsp;';
1467
1468                     var t = new Date(timestamp * 1000);
1469                     var now = new Date();
1470
1471                     if(t.toDateString() == now.toDateString())
1472                         return t.toLocaleTimeString();
1473
1474                     return t.toLocaleDateString() + space + t.toLocaleTimeString();
1475                 }
1476
1477                 function seconds4human(seconds, options) {
1478                     var default_options = {
1479                         now: 'now',
1480                         space: '&nbsp;',
1481                         negative_suffix: 'ago',
1482                         hour: 'hour',
1483                         hours: 'hours',
1484                         minute: 'minute',
1485                         minutes: 'minutes',
1486                         second: 'second',
1487                         seconds: 'seconds',
1488                         and: 'and'
1489                     };
1490
1491                     if(typeof options !== 'object')
1492                         options = default_options;
1493                     else {
1494                         var x;
1495                         for(x in default_options) {
1496                             if(typeof options[x] !== 'string')
1497                                 options[x] = default_options[x];
1498                         }
1499                     }
1500
1501                     if(typeof seconds === 'string')
1502                         seconds = parseInt(seconds);
1503
1504                     if(seconds === 0)
1505                         return options.now;
1506
1507                     var suffix = '';
1508                     if(seconds < 0) {
1509                         seconds = -seconds;
1510                         if(options.negative_suffix !== '') suffix = options.space + options.negative_suffix;
1511                     }
1512
1513                     var hours = Math.floor(seconds / 3600);
1514                     seconds -= (hours * 3600);
1515
1516                     var minutes = Math.floor(seconds / 60);
1517                     seconds -= (minutes * 60);
1518
1519                     var txt = '';
1520
1521                     if(hours > 1) txt += hours.toString() + options.space + options.hours;
1522                     else if(hours === 1) txt += hours.toString() + options.space + options.hour;
1523
1524                     if(hours > 0 && minutes > 0 && seconds == 0)
1525                         txt += options.space + options.and + options.space;
1526                     else if(hours > 0 && minutes > 0 && seconds > 0)
1527                         txt += ',' + options.space;
1528
1529                     if(minutes > 1) txt += minutes.toString() + options.space + options.minutes;
1530                     else if(minutes === 1) txt += minutes.toString() + options.space + options.minute;
1531
1532                     if((minutes > 0 || minutes > 0) && seconds > 0)
1533                         txt += options.space + options.and + options.space;
1534
1535                     if(seconds > 1) txt += Math.floor(seconds).toString() + options.space + options.seconds;
1536                     else if(seconds === 1) txt += Math.floor(seconds).toString() + options.space + options.second;
1537
1538                     return txt + suffix;
1539                 }
1540
1541                 function alarm_lookup_explain(alarm, chart) {
1542                     var dimensions = ' of all values ';
1543
1544                     if(chart.dimensions.length > 1)
1545                         dimensions = ' of the sum of all dimensions ';
1546
1547                     if(typeof alarm.lookup_dimensions !== 'undefined') {
1548                         var d = alarm.lookup_dimensions.replace('|', ',');
1549                         var x = d.split(',');
1550                         if(x.length > 1)
1551                             dimensions = 'of the sum of dimensions <code>' + alarm.lookup_dimensions + '</code> ';
1552                         else
1553                             dimensions = 'of all values of dimension <code>' + alarm.lookup_dimensions + '</code> ';
1554                     }
1555
1556                     return '<code>' + alarm.lookup_method + '</code> '
1557                         + dimensions + ', of chart <code>' + alarm.chart + '</code>'
1558                         + ', starting <code>' + seconds4human(alarm.lookup_after + alarm.lookup_before) + '</code> and up to <code>' + seconds4human(alarm.lookup_before) + '</code>'
1559                         + ((alarm.lookup_options)?(', with options <code>' + alarm.lookup_options.replace(' ', ',&nbsp;') + '</code>'):'')
1560                         + '.';
1561                 }
1562
1563                 function alarm_to_html(alarm, full) {
1564                     var chart = options.data.charts[alarm.chart];
1565                     var has_alarm = ((typeof alarm.warn !== 'undefined' || typeof alarm.crit !== 'undefined')?true:false);
1566
1567                     var role_href = ((has_alarm === true)?('<br/>&nbsp;<br/>role: <b>' + alarm.recipient + '</b><br/>&nbsp;<br/><b><i class="fa fa-line-chart" aria-hidden="true"></i></b><small>&nbsp;&nbsp;<a href="#" onClick="NETDATA.alarms.scrollToChart(\'' + alarm.chart + '\'); $(\'#alarmsModal\').modal(\'hide\'); return false;">jump to chart</a></small>'):('&nbsp;'));
1568
1569                     var html = '<tr><td class="text-center" style="vertical-align:middle" width="40%"><b>' + alarm.chart + '</b><br/>&nbsp;<br/><embed src="' + NETDATA.alarms.server + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto" type="image/svg+xml" height="20"/><br/>&nbsp;<br/><span style="font-size: 18px">' + alarm.info + '</span>' + role_href + '</td>'
1570                         + '<td><table class="table">'
1571                         + ((typeof alarm.warn !== 'undefined')?('<tr><td width="10%" style="text-align:right">warning&nbsp;when</td><td><span style="font-family: monospace; color:#fe7d37; font-weight: bold;">' + alarm.warn + '</span></td></tr>'):'')
1572                         + ((typeof alarm.crit !== 'undefined')?('<tr><td width="10%" style="text-align:right">critical&nbsp;when</td><td><span style="font-family: monospace; color: #e05d44; font-weight: bold;">' + alarm.crit + '</span></td></tr>'):'');
1573
1574                     if(full === true) {
1575                             html += ((typeof alarm.lookup_after !== 'undefined')?('<tr><td width="10%" style="text-align:right">db&nbsp;lookup</td><td>' + alarm_lookup_explain(alarm, chart) + '</td></tr>'):'')
1576                             + ((typeof alarm.calc !== 'undefined')?('<tr><td width="10%" style="text-align:right">calculation</td><td><span style="font-family: monospace;">' + alarm.calc + '</span></td></tr>'):'')
1577                             + ((chart.green !== null)?('<tr><td width="10%" style="text-align:right">green&nbsp;threshold</td><td><code>' + chart.green + ' ' + chart.units + '</code></td></tr>'):'')
1578                             + ((chart.red !== null)?('<tr><td width="10%" style="text-align:right">red&nbsp;threshold</td><td><code>' + chart.red + ' ' + chart.units + '</code></td></tr>'):'');
1579                     }
1580
1581                     var delay = '';
1582                     if((alarm.delay_up_duration > 0 || alarm.delay_down_duration > 0) && alarm.delay_multiplier != 0 && alarm.delay_max_duration > 0) {
1583                         if(alarm.delay_up_duration == alarm.delay_down_duration) {
1584                             delay += '<small><br/>hysteresis ' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' });
1585                         }
1586                         else {
1587                             delay = '<small><br/>hysteresis ';
1588                             if(alarm.delay_up_duration > 0) {
1589                                 delay += 'on&nbsp;escalation&nbsp;<code>' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' }) + '</code>, ';
1590                             }
1591                             if(alarm.delay_down_duration > 0) {
1592                                 delay += 'on&nbsp;recovery&nbsp;<code>' + seconds4human(alarm.delay_down_duration, { negative_suffix: '' }) + '</code>, ';
1593                             }
1594                         }
1595                         if(alarm.delay_multiplier != 1.0) {
1596                             delay += 'multiplied&nbsp;by&nbsp;<code>' + alarm.delay_multiplier.toString() + '</code>';
1597                             delay += ',&nbsp;up&nbsp;to&nbsp;<code>' + seconds4human(alarm.delay_max_duration, { negative_suffix: '' }) + '</code>';
1598                         }
1599                         delay += '</small>';
1600                     }
1601
1602                     html += '<tr><td width="10%" style="text-align:right">check&nbsp;every</td><td>' + seconds4human(alarm.update_every, { negative_suffix: '' }) + '</td></tr>'
1603                         + ((has_alarm === true)?('<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span>' + delay + '</td></tr>'):'')
1604                         + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>'
1605                         + '</table></td></tr>';
1606
1607                     return html;
1608                 }
1609
1610                 function alarm_family_show(id) {
1611                     var html = '<table class="table">';
1612                     var family = options.alarm_families[id];
1613                     var len = family.arr.length;
1614                     while(len--) {
1615                         var alarm = family.arr[len];
1616                         html += alarm_to_html(alarm, true);
1617                     }
1618                     html += '</table>';
1619
1620                     $('#alarm_all_' + id.toString()).html(html);
1621                 }
1622
1623                 // find the proper family of each alarm
1624                 var now = Date.now();
1625                 var x;
1626                 var count_active = 0;
1627                 var count_all = 0;
1628                 var families = {};
1629                 var families_sort = new Array();
1630                 for(x in data.alarms) {
1631                     var alarm = data.alarms[x];
1632                     var family = alarm.family;
1633
1634                     // find the chart
1635                     var chart = options.data.charts[alarm.chart];
1636                     if(typeof chart === 'undefined')
1637                         chart = options.data.charts_by_name[alarm.chart];
1638
1639                     // not found - this should never happen!
1640                     if(typeof chart === 'undefined') {
1641                         console.log('WARNING: alarm ' + x + ' is linked to chart ' + alarm.chart + ', which is not found in the list of chart got from the server.');
1642                         chart = { priority: 9999999 };
1643                     }
1644                     else if(typeof chart.menu !== 'undefined' && typeof chart.submenu !== 'undefined')
1645                         // the family based on the chart
1646                         family = chart.menu + ' - ' + chart.submenu;
1647
1648                     if(typeof families[family] === 'undefined') {
1649                         families[family] = {
1650                             name: family,
1651                             arr: new Array(),
1652                             priority: chart.priority
1653                         };
1654
1655                         families_sort.push(families[family]);
1656                     }
1657
1658                     if(chart.priority < families[family].priority)
1659                         families[family].priority = chart.priority;
1660
1661                     families[family].arr.unshift(alarm);
1662                 }
1663
1664                 // sort the families, like the dashboard menu does
1665                 var families_sorted = families_sort.sort(function (a, b) {
1666                     if (a.priority > b.priority) return -1;
1667                     if (a.priority < b.priority) return 1;
1668                     return 0;
1669                 });
1670
1671                 var fc = 0;
1672                 var len = families_sorted.length;
1673                 while(len--) {
1674                     var family = families_sorted[len].name;
1675                     var active_family_added = false;
1676                     var expanded = 'true';
1677                     var collapsed = '';
1678                     var cin = 'in';
1679
1680                     if(fc !== 0) {
1681                         all += "</table></div></div></div>";
1682                         expanded = 'false';
1683                         collapsed = 'class="collapsed"'
1684                         cin = '';
1685                     }
1686
1687                     all += '<div class="panel panel-default"><div class="panel-heading" role="tab" id="alarm_all_heading_' + fc.toString() + '"><h4 class="panel-title"><a ' + collapsed + ' role="button" data-toggle="collapse" data-parent="#alarms_all_accordion" href="#alarm_all_' + fc.toString() + '" aria-expanded="' + expanded + '" aria-controls="alarm_all_' + fc.toString() + '">' + family.toString() + '</a></h4></div><div id="alarm_all_' + fc.toString() + '" class="panel-collapse collapse ' + cin + '" role="tabpanel" aria-labelledby="alarm_all_heading_' + fc.toString() + '" data-alarm-id="' + fc.toString() + '"><div class="panel-body" id="alarm_all_body_' + fc.toString() + '">';
1688
1689                     options.alarm_families[fc] = families[family];
1690
1691                     fc++;
1692
1693                     var arr = families[family].arr;
1694                     var c = arr.length;
1695                     while(c--) {
1696                         var alarm = arr[c];
1697                         if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') {
1698                             if(!active_family_added) {
1699                                 active_family_added = true;
1700                                 active += '<tr><th class="text-center" colspan="2"><h4>' + family + '</h4></th></tr>';
1701                             }
1702                             count_active++;
1703                             active += alarm_to_html(alarm, true);
1704                         }
1705
1706                         count_all++;
1707                     }
1708                 }
1709                 active += "</table>";
1710                 if(families_sorted.length > 0) all += "</div></div></div>";
1711                 all += "</div>";
1712
1713                 if(!count_active)
1714                     active += "<h4>Everything is normal. No raised alarms.</h4>";
1715                 else
1716                     active += footer;
1717
1718                 if(!count_all)
1719                     all += "<h4>No alarms are running in this system.</h4>";
1720                 else
1721                     all += footer;
1722
1723                 document.getElementById('alarms_active').innerHTML = active;
1724                 document.getElementById('alarms_all').innerHTML = all;
1725
1726                 if(families_sorted.length > 0) alarm_family_show(0);
1727
1728                 // register bootstrap events
1729                 $('#alarms_all_accordion').on('show.bs.collapse', function (d) {
1730                     var target = $(d.target);
1731                     var id = $(target).data('alarm-id');
1732                     alarm_family_show(id);
1733                 });
1734                 $('#alarms_all_accordion').on('hidden.bs.collapse', function (d) {
1735                     var target = $(d.target);
1736                     var id = $(target).data('alarm-id');
1737                     $('#alarm_all_' + id.toString()).html('');
1738                 });
1739
1740                 document.getElementById('alarms_log').innerHTML = '<h3>Alarm Log</h3><table id="alarms_log_table"></table>';
1741
1742                 loadBootstrapTable(function () {
1743                     $('#alarms_log_table').bootstrapTable({
1744                         url: NETDATA.alarms.server + '/api/v1/alarm_log?all',
1745                         cache: false,
1746                         pagination: true,
1747                         pageSize: 10,
1748                         showPaginationSwitch: false,
1749                         search: true,
1750                         searchTimeOut: 300,
1751                         searchAlign: 'left',
1752                         showColumns: true,
1753                         showExport: true,
1754                         exportDataType: 'basic',
1755                         exportOptions: {
1756                             fileName: 'netdata_alarm_log'
1757                         },
1758                         rowStyle: function(row, index) {
1759                             switch(row.status) {
1760                                 case 'CRITICAL' : return { classes: 'danger'  }; break;
1761                                 case 'WARNING'  : return { classes: 'warning' }; break;
1762                                 case 'UNDEFINED': return { classes: 'info'    }; break;
1763                                 case 'CLEAR'    : return { classes: 'success' }; break;
1764                             }
1765                             return {};
1766                         },
1767                         showFooter: false,
1768                         showHeader: true,
1769                         showRefresh: true,
1770                         showToggle: false,
1771                         sortable: true,
1772                         silentSort: false,
1773                         columns: [
1774                             {
1775                                 field: 'when',
1776                                 title: 'Event Date',
1777                                 valign: 'middle',
1778                                 titleTooltip: 'The date and time the even took place',
1779                                 formatter: function(value, row, index) { return timestamp4human(value, ' '); },
1780                                 align: 'center',
1781                                 valign: 'middle',
1782                                 switchable: false,
1783                                 sortable: true
1784                             },
1785                             {
1786                                 field: 'hostname',
1787                                 title: 'Host',
1788                                 valign: 'middle',
1789                                 titleTooltip: 'The host that generated this event',
1790                                 align: 'center',
1791                                 valign: 'middle',
1792                                 visible: false,
1793                                 sortable: true
1794                             },
1795                             {
1796                                 field: 'unique_id',
1797                                 title: 'Unique ID',
1798                                 titleTooltip: 'The host unique ID for this event',
1799                                 formatter: function(value, row, index) { return alarmid4human(value); },
1800                                 align: 'center',
1801                                 valign: 'middle',
1802                                 visible: false,
1803                                 sortable: true
1804                             },
1805                             {
1806                                 field: 'alarm_id',
1807                                 title: 'Alarm ID',
1808                                 titleTooltip: 'The ID of the alarm that generated this event',
1809                                 formatter: function(value, row, index) { return alarmid4human(value); },
1810                                 align: 'center',
1811                                 valign: 'middle',
1812                                 visible: false,
1813                                 sortable: true
1814                             },
1815                             {
1816                                 field: 'alarm_event_id',
1817                                 title: 'Alarm Event ID',
1818                                 titleTooltip: 'The incremental ID of this event for the given alarm',
1819                                 formatter: function(value, row, index) { return alarmid4human(value); },
1820                                 align: 'center',
1821                                 valign: 'middle',
1822                                 visible: false,
1823                                 sortable: true
1824                             },
1825                             {
1826                                 field: 'chart',
1827                                 title: 'Chart',
1828                                 titleTooltip: 'The chart the alarm is attached to',
1829                                 align: 'center',
1830                                 valign: 'middle',
1831                                 switchable: false,
1832                                 sortable: true
1833                             },
1834                             {
1835                                 field: 'family',
1836                                 title: 'Family',
1837                                 titleTooltip: 'The family of the chart the alarm is attached to',
1838                                 align: 'center',
1839                                 valign: 'middle',
1840                                 visible: false,
1841                                 sortable: true
1842                             },
1843                             {
1844                                 field: 'name',
1845                                 title: 'Alarm',
1846                                 titleTooltip: 'The alarm name that generated this event',
1847                                 formatter: function(value, row, index) {
1848                                     return value.toString().replace(/_/g, ' ');
1849                                 },
1850                                 align: 'center',
1851                                 valign: 'middle',
1852                                 switchable: false,
1853                                 sortable: true
1854                             },
1855                             {
1856                                 field: 'old_value',
1857                                 title: 'Old Value',
1858                                 titleTooltip: 'The value of the alarm, just before this event',
1859                                 formatter: function(value, row, index) {
1860                                     return ((value !== null)?Math.round(value * 100) / 100:'NaN').toString();
1861                                 },
1862                                 align: 'center',
1863                                 valign: 'middle',
1864                                 visible: false,
1865                                 sortable: true
1866                             },
1867                             {
1868                                 field: 'value',
1869                                 title: 'Value',
1870                                 titleTooltip: 'The value of the alarm, that triggered this event',
1871                                 formatter: function(value, row, index) {
1872                                     return ((value !== null)?Math.round(value * 100) / 100:'NaN').toString();
1873                                 },
1874                                 align: 'right',
1875                                 valign: 'middle',
1876                                 sortable: true
1877                             },
1878                             {
1879                                 field: 'units',
1880                                 title: 'Units',
1881                                 titleTooltip: 'The units of the value of the alarm',
1882                                 align: 'left',
1883                                 valign: 'middle',
1884                                 sortable: true
1885                             },
1886                             {
1887                                 field: 'old_status',
1888                                 title: 'Old Status',
1889                                 titleTooltip: 'The status of the alarm, just before this event',
1890                                 align: 'center',
1891                                 valign: 'middle',
1892                                 visible: false,
1893                                 sortable: true
1894                             },
1895                             {
1896                                 field: 'status',
1897                                 title: 'Status',
1898                                 titleTooltip: 'The status of the alarm, that was set due to this event',
1899                                 align: 'center',
1900                                 valign: 'middle',
1901                                 switchable: false,
1902                                 sortable: true
1903                             },
1904                             {
1905                                 field: 'duration',
1906                                 title: 'Last Duration',
1907                                 titleTooltip: 'The duration the alarm was at its previous state, just before this event',
1908                                 formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); },
1909                                 align: 'center',
1910                                 valign: 'middle',
1911                                 visible: false,
1912                                 sortable: true
1913                             },
1914                             {
1915                                 field: 'non_clear_duration',
1916                                 title: 'Raised Duration',
1917                                 titleTooltip: 'The duration the alarm was raised, just before this event',
1918                                 formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); },
1919                                 align: 'center',
1920                                 valign: 'middle',
1921                                 visible: false,
1922                                 sortable: true
1923                             },
1924                             {
1925                                 field: 'recipient',
1926                                 title: 'Recipient',
1927                                 titleTooltip: 'The recipient of this event',
1928                                 align: 'center',
1929                                 valign: 'middle',
1930                                 visible: false,
1931                                 sortable: true
1932                             },
1933                             {
1934                                 field: 'processed',
1935                                 title: 'Processed Status',
1936                                 titleTooltip: 'True when this event is processed',
1937                                 formatter: function(value, row, index) {
1938                                     if(value === true)
1939                                         return 'DONE';
1940                                     else
1941                                         return 'PENDING';
1942                                 },
1943                                 align: 'center',
1944                                 valign: 'middle',
1945                                 visible: false,
1946                                 sortable: true
1947                             },
1948                             {
1949                                 field: 'updated',
1950                                 title: 'Updated Status',
1951                                 titleTooltip: 'True when this event has been updated by another event',
1952                                 formatter: function(value, row, index) {
1953                                     if(value === true)
1954                                         return 'UPDATED';
1955                                     else
1956                                         return 'CURRENT';
1957                                 },
1958                                 align: 'center',
1959                                 valign: 'middle',
1960                                 visible: false,
1961                                 sortable: true
1962                             },
1963                             {
1964                                 field: 'updated_by_id',
1965                                 title: 'Updated By ID',
1966                                 titleTooltip: 'The unique ID of the event that obsoleted this one',
1967                                 formatter: function(value, row, index) { return alarmid4human(value); },
1968                                 align: 'center',
1969                                 valign: 'middle',
1970                                 visible: false,
1971                                 sortable: true
1972                             },
1973                             {
1974                                 field: 'updates_id',
1975                                 title: 'Updates ID',
1976                                 titleTooltip: 'The unique ID of the event obsoleted because of this event',
1977                                 formatter: function(value, row, index) { return alarmid4human(value); },
1978                                 align: 'center',
1979                                 valign: 'middle',
1980                                 visible: false,
1981                                 sortable: true
1982                             },
1983                             {
1984                                 field: 'exec',
1985                                 title: 'Script',
1986                                 titleTooltip: 'The script to handle the event notification',
1987                                 align: 'center',
1988                                 valign: 'middle',
1989                                 visible: false,
1990                                 sortable: true
1991                             },
1992                             {
1993                                 field: 'exec_run',
1994                                 title: 'Script Run At',
1995                                 titleTooltip: 'The date and time the script has been ran',
1996                                 formatter: function(value, row, index) { return timestamp4human(value, ' '); },
1997                                 align: 'center',
1998                                 valign: 'middle',
1999                                 visible: false,
2000                                 sortable: true
2001                             },
2002                             {
2003                                 field: 'exec_code',
2004                                 title: 'Script Return Value',
2005                                 titleTooltip: 'The return code of the script',
2006                                 formatter: function(value, row, index) {
2007                                     if(value === 0)
2008                                         return 'OK (returned 0)';
2009                                     else
2010                                         return 'FAILED (with code ' + value.toString() + ')';
2011                                 },
2012                                 align: 'center',
2013                                 valign: 'middle',
2014                                 visible: false,
2015                                 sortable: true
2016                             },
2017                             {
2018                                 field: 'delay',
2019                                 title: 'Script Delay',
2020                                 titleTooltip: 'The hysteresis of the notification',
2021                                 formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); },
2022                                 align: 'center',
2023                                 valign: 'middle',
2024                                 visible: false,
2025                                 sortable: true
2026                             },
2027                             {
2028                                 field: 'delay_up_to_timestamp',
2029                                 title: 'Script Delay Run At',
2030                                 titleTooltip: 'The date and time the script should be run, after hysteresis',
2031                                 formatter: function(value, row, index) { return timestamp4human(value, ' '); },
2032                                 align: 'center',
2033                                 valign: 'middle',
2034                                 visible: false,
2035                                 sortable: true
2036                             },
2037                             {
2038                                 field: 'info',
2039                                 title: 'Description',
2040                                 titleTooltip: 'A short description of the alarm',
2041                                 align: 'center',
2042                                 valign: 'middle',
2043                                 visible: false,
2044                                 sortable: true
2045                             },
2046                             {
2047                                 field: 'source',
2048                                 title: 'Alarm Source',
2049                                 titleTooltip: 'The source of configuration of the alarm',
2050                                 align: 'center',
2051                                 valign: 'middle',
2052                                 visible: false,
2053                                 sortable: true
2054                             }
2055                         ]
2056                     });
2057                     // console.log($('#alarms_log_table').bootstrapTable('getOptions'));
2058                 });
2059             });
2060         }
2061
2062         function alarmsCallback(data) {
2063             var count = 0;
2064             for(x in data.alarms) {
2065                 var alarm = data.alarms[x];
2066                 if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL')
2067                     count++;
2068             }
2069
2070             if(count > 0)
2071                 document.getElementById('alarms_count_badge').innerHTML = count.toString();
2072             else
2073                 document.getElementById('alarms_count_badge').innerHTML = '';
2074         }
2075
2076         function initializeDynamicDashboard(netdata_url) {
2077             if(typeof netdata_url === 'undefined' || netdata_url === null)
2078                 netdata_url = NETDATA.serverDefault;
2079
2080             // initialize clickable alarms
2081             NETDATA.alarms.chart_div_offset = 100;
2082             NETDATA.alarms.chart_div_id_prefix = 'chart_';
2083             NETDATA.alarms.chart_div_animation_duration = 0;
2084
2085             NETDATA.pause(function() {
2086                 NETDATA.alarms.callback = alarmsCallback;
2087
2088                 // download all the charts the server knows
2089                 NETDATA.chartRegistry.downloadAll(netdata_url, function(data) {
2090                     if(data !== null) {
2091                         options.hostname = data.hostname;
2092                         options.data = data;
2093
2094                         // update the dashboard hostname
2095                         document.getElementById('hostname').innerHTML = options.hostname;
2096                         document.getElementById('hostname').href = NETDATA.serverDefault;
2097
2098                         // update the dashboard title
2099                         document.title = options.hostname + ' netdata dashboard';
2100
2101                         // close the splash screen
2102                         $("#loadOverlay").css("display","none");
2103
2104                         // create a chart_by_name index
2105                         data.charts_by_name = {};
2106                         var charts = data.charts;
2107                         var x;
2108                         for(x in charts) {
2109                             var chart = charts[x];
2110                             data.charts_by_name[chart.name] = chart;
2111                         }
2112
2113                         // render all charts
2114                         renderChartsAndMenu(data);
2115                     }
2116                 });
2117             });
2118         }
2119
2120         // ----------------------------------------------------------------------------
2121
2122         function versionLog(msg) {
2123             document.getElementById('versionCheckLog').innerHTML = msg;
2124         }
2125
2126         function getNetdataVersion(callback) {
2127             versionLog('Downloading installed version info from netdata...');
2128
2129             $.ajax({
2130                 url: 'version.txt',
2131                 async: true,
2132                 cache: false,
2133                 xhrFields: { withCredentials: true } // required for the cookie
2134             })
2135             .done(function(data) {
2136                 data = data.replace(/(\r\n|\n|\r| |\t)/gm,"");
2137                 if(data.length !== 40) {
2138                     versionLog('Received version string is invalid.');
2139                     callback(null);
2140                 }
2141                 else {
2142                     versionLog('Installed version of netdata is ' + data);
2143                     document.getElementById('netdataVersion').innerHTML = data;
2144                     callback(data);
2145                 }
2146             })
2147             .fail(function() {
2148                 versionLog('Failed to download installed version info from netdata!');
2149                 callback(null);
2150             });
2151         }
2152
2153         function getGithubLatestCommit(callback) {
2154             versionLog('Downloading latest version info from github...');
2155
2156             $.ajax({
2157                 url: 'https://api.github.com/repos/firehol/netdata/commits',
2158                 async: true,
2159                 cache: false
2160             })
2161             .done(function(data) {
2162                 versionLog('Latest version info from github is ' + data[0].sha);
2163                 callback(data[0].sha);
2164             })
2165             .fail(function() {
2166                 versionLog('Failed to download installed version info from github!');
2167                 callback(null);
2168             });
2169         }
2170
2171         function checkForUpdate(callback) {
2172             getNetdataVersion(function(sha1) {
2173                 if(sha1 === null) callback(null, null);
2174
2175                 getGithubLatestCommit(function(sha2) {
2176                     callback(sha1, sha2);
2177                 });
2178             });
2179
2180             return null;
2181         }
2182
2183         function notifyForUpdate(force) {
2184             versionLog('<p>checking for updates...</p>');
2185
2186             var now = Date.now();
2187
2188             if(typeof force === 'undefined' || force !== true) {
2189                 var last = loadLocalStorage('last_update_check');
2190
2191                 if(typeof last === 'string')
2192                     last = parseInt(last);
2193                 else
2194                     last = 0;
2195
2196                 if(now - last < 3600000 * 8) {
2197                     // no need to check it - too soon
2198                     return;
2199                 }
2200             }
2201
2202             checkForUpdate(function(sha1, sha2) {
2203                 var save = false;
2204
2205                 if(sha1 === null) {
2206                     save = false;
2207                     versionLog('<p><big>Failed to get your netdata version!</big></p><p>You can always get the latest version of netdata from <a href="https://github.com/firehol/netdata" target="_blank">its github page</a>.</p>');
2208                 }
2209                 else if(sha2 === null) {
2210                     save = false;
2211                     versionLog('<p><big>Failed to get the latest version from github.</big></p><p>You can always get the latest version of netdata from <a href="https://github.com/firehol/netdata" target="_blank">its github page</a>.</p>');
2212                 }
2213                 else if(sha1 === sha2) {
2214                     save = true;
2215                     versionLog('<p><big>You already have the latest version of netdata!</big></p><p>No update yet?<br/>Probably, we need some motivation to keep going on!</p><p>If you haven\'t already, <a href="https://github.com/firehol/netdata" target="_blank">give netdata a <b>Star</b> at its github page</a>.</p>');
2216                 }
2217                 else {
2218                     save = true;
2219                     var compare = 'https://github.com/firehol/netdata/compare/' + sha1.toString() + '...' + sha2.toString();
2220
2221                     versionLog('<p><big><strong>New version of netdata available!</strong></big></p><p>Latest version: ' + sha2.toString() + '</p><p><a href="' + compare + '" target="_blank">Click here for the changes log</a> since your installed version, and<br/><a href="https://github.com/firehol/netdata/wiki/Updating-Netdata" target="_blank">click here for directions on updating</a> your netdata installation.</p><p>We suggest to review the changes log for new features you may be interested, or important bug fixes you may need.<br/>Keeping your netdata updated, is generally a good idea.</p>');
2222
2223                     document.getElementById('update_badge').innerHTML = '!';
2224                 }
2225
2226                 if(save)
2227                     saveLocalStorage('last_update_check', now.toString());
2228             });
2229         }
2230
2231         // ----------------------------------------------------------------------------
2232
2233         function finalizePage() {
2234             // resize all charts - without starting the background thread
2235             // this has to be done while NETDATA is paused
2236             // if we ommit this, the affix menu will be wrong, since all
2237             // the Dom elements are initially zero-sized
2238             NETDATA.parseDom();
2239
2240             if(urlOptions.pan_and_zoom === true)
2241                 NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before);
2242
2243             // ------------------------------------------------------------------------
2244             // https://github.com/viralpatel/jquery.shorten/blob/master/src/jquery.shorten.js
2245             $.fn.shorten = function(settings) {
2246                 "use strict";
2247
2248                 var config = {
2249                     showChars: 750,
2250                     minHideChars: 10,
2251                     ellipsesText: "...",
2252                     moreText: '<i class="fa fa-expand" aria-hidden="true"></i> show more information',
2253                     lessText: '<i class="fa fa-compress" aria-hidden="true"></i> show less information',
2254                     onLess: function() { NETDATA.onscroll(); },
2255                     onMore: function() { NETDATA.onscroll(); },
2256                     errMsg: null,
2257                     force: false
2258                 };
2259
2260                 if (settings) {
2261                     $.extend(config, settings);
2262                 }
2263
2264                 if ($(this).data('jquery.shorten') && !config.force) {
2265                     return false;
2266                 }
2267                 $(this).data('jquery.shorten', true);
2268
2269                 $(document).off("click", '.morelink');
2270
2271                 $(document).on({
2272                     click: function() {
2273
2274                         var $this = $(this);
2275                         if ($this.hasClass('less')) {
2276                             $this.removeClass('less');
2277                             $this.html(config.moreText);
2278                             $this.parent().prev().animate({'height':'0'+'%'}, 0, function () { $this.parent().prev().prev().show(); }).hide(0, function() {
2279                                 config.onLess();
2280                             });
2281
2282                         } else {
2283                             $this.addClass('less');
2284                             $this.html(config.lessText);
2285                             $this.parent().prev().animate({'height':'100'+'%'}, 0, function () { $this.parent().prev().prev().hide(); }).show(0, function() {
2286                                 config.onMore();
2287                             });
2288                         }
2289                         return false;
2290                     }
2291                 }, '.morelink');
2292
2293                 return this.each(function() {
2294                     var $this = $(this);
2295
2296                     var content = $this.html();
2297                     var contentlen = $this.text().length;
2298                     if (contentlen > config.showChars + config.minHideChars) {
2299                         var c = content.substr(0, config.showChars);
2300                         if (c.indexOf('<') >= 0) // If there's HTML don't want to cut it
2301                         {
2302                             var inTag = false; // I'm in a tag?
2303                             var bag = ''; // Put the characters to be shown here
2304                             var countChars = 0; // Current bag size
2305                             var openTags = []; // Stack for opened tags, so I can close them later
2306                             var tagName = null;
2307
2308                             for (var i = 0, r = 0; r <= config.showChars; i++) {
2309                                 if (content[i] == '<' && !inTag) {
2310                                     inTag = true;
2311
2312                                     // This could be "tag" or "/tag"
2313                                     tagName = content.substring(i + 1, content.indexOf('>', i));
2314
2315                                     // If its a closing tag
2316                                     if (tagName[0] == '/') {
2317
2318
2319                                         if (tagName != '/' + openTags[0]) {
2320                                             config.errMsg = 'ERROR en HTML: the top of the stack should be the tag that closes';
2321                                         } else {
2322                                             openTags.shift(); // Pops the last tag from the open tag stack (the tag is closed in the retult HTML!)
2323                                         }
2324
2325                                     } else {
2326                                         // There are some nasty tags that don't have a close tag like <br/>
2327                                         if (tagName.toLowerCase() != 'br') {
2328                                             openTags.unshift(tagName); // Add to start the name of the tag that opens
2329                                         }
2330                                     }
2331                                 }
2332                                 if (inTag && content[i] == '>') {
2333                                     inTag = false;
2334                                 }
2335
2336                                 if (inTag) { bag += content.charAt(i); } // Add tag name chars to the result
2337                                 else {
2338                                     r++;
2339                                     if (countChars <= config.showChars) {
2340                                         bag += content.charAt(i); // Fix to ie 7 not allowing you to reference string characters using the []
2341                                         countChars++;
2342                                     } else // Now I have the characters needed
2343                                     {
2344                                         if (openTags.length > 0) // I have unclosed tags
2345                                         {
2346                                             //console.log('They were open tags');
2347                                             //console.log(openTags);
2348                                             for (j = 0; j < openTags.length; j++) {
2349                                                 //console.log('Cierro tag ' + openTags[j]);
2350                                                 bag += '</' + openTags[j] + '>'; // Close all tags that were opened
2351
2352                                                 // You could shift the tag from the stack to check if you end with an empty stack, that means you have closed all open tags
2353                                             }
2354                                             break;
2355                                         }
2356                                     }
2357                                 }
2358                             }
2359                             c = $('<div/>').html(bag + '<span class="ellip">' + config.ellipsesText + '</span>').html();
2360                         }else{
2361                             c+=config.ellipsesText;
2362                         }
2363
2364                         var html = '<div class="shortcontent">' + c +
2365                                 '</div><div class="allcontent">' + content +
2366                                 '</div><span><a href="javascript://nop/" class="morelink">' + config.moreText + '</a></span>';
2367
2368                         $this.html(html);
2369                         $this.find(".allcontent").hide(); // Hide all text
2370                         $('.shortcontent p:last', $this).css('margin-bottom', 0); //Remove bottom margin on last paragraph as it's likely shortened
2371                     }
2372                 });
2373
2374             };
2375             $(".chart-message").shorten();
2376             // ------------------------------------------------------------------------
2377
2378             // callback for us to track PanAndZoom operations
2379             NETDATA.globalPanAndZoom.callback = urlOptions.netdataPanAndZoomCallback;
2380
2381             // let it run (update the charts)
2382             NETDATA.unpause();
2383
2384             // check if we have to jump to a specific section
2385             scrollToId(urlOptions.hash.replace('#',''));
2386
2387             if(urlOptions.chart !== null) {
2388                 NETDATA.alarms.scrollToChart(urlOptions.chart);
2389                 //urlOptions.hash = '#' + NETDATA.name2id('menu_' + charts[c].menu + '_submenu_' + charts[c].submenu);
2390                 //urlOptions.hash = '#chart_' + NETDATA.name2id(urlOptions.chart);
2391                 //console.log('hash = ' + urlOptions.hash);
2392             }
2393
2394             /* activate bootstrap sidebar (affix) */
2395             $('#sidebar').affix({
2396                 offset: {
2397                     top: (isdemo())?150:0,
2398                     bottom: 0
2399                 }
2400             });
2401
2402             /* fix scrolling of very long affix lists
2403                http://stackoverflow.com/questions/21691585/bootstrap-3-1-0-affix-too-long
2404              */
2405             $('#sidebar').on('affixed.bs.affix', function() {
2406                 $(this).removeAttr('style');
2407             });
2408
2409             /* activate bootstrap scrollspy (needed for sidebar) */
2410             $(document.body).scrollspy({
2411                 target: '#sidebar',
2412                 offset: $(window).height() / 5 // controls the diff of the <hX> element to the top, to select it
2413             });
2414
2415             // change the URL based on the current position of the screen
2416             $('#sidebar').on('activate.bs.scrollspy', function (e) {
2417                 // console.log(e);
2418                 var el = $(e.target);
2419                 //if(el.find('ul').size() == 0) {
2420                 var hash = el.find('a').attr('href');
2421                 if(typeof hash === 'string' && hash.substring(0, 1) === '#' && urlOptions.hash.startsWith(hash + '_submenu_') === false) {
2422                     urlOptions.hash = hash;
2423                     //console.log(urlOptions.hash);
2424                     urlOptions.hashUpdate();
2425                 }
2426                 //else console.log('hash: not accepting ' + hash);
2427                 //}
2428                 //else console.log('el.find(): not found');
2429             });
2430
2431             document.getElementById('footer').style.display = 'block';
2432
2433             var update_options_modal = function() {
2434                 // console.log('update_options_modal');
2435
2436                 var sync_option = function(option) {
2437                     var self = $('#' + option);
2438
2439                     if(self.prop('checked') !== NETDATA.getOption(option)) {
2440                         // console.log('switching ' + option.toString());
2441                         self.bootstrapToggle(NETDATA.getOption(option)?'on':'off');
2442                     }
2443                 }
2444
2445                 var theme_sync_option = function(option) {
2446                     var self = $('#' + option);
2447
2448                     self.bootstrapToggle(netdataTheme === 'slate'?'on':'off');
2449                 }
2450
2451                 sync_option('eliminate_zero_dimensions');
2452                 sync_option('destroy_on_hide');
2453                 sync_option('async_on_scroll');
2454                 sync_option('parallel_refresher');
2455                 sync_option('concurrent_refreshes');
2456                 sync_option('sync_selection');
2457                 sync_option('sync_pan_and_zoom');
2458                 sync_option('stop_updates_when_focus_is_lost');
2459                 sync_option('smooth_plot');
2460                 sync_option('pan_and_zoom_data_padding');
2461                 sync_option('show_help');
2462                 theme_sync_option('netdata_theme_control');
2463
2464                 if(NETDATA.getOption('parallel_refresher') === false) {
2465                     $('#concurrent_refreshes_row').hide();
2466                 }
2467                 else {
2468                     $('#concurrent_refreshes_row').show();
2469                 }
2470             };
2471             NETDATA.setOption('setOptionCallback', update_options_modal);
2472
2473             // handle options changes
2474             $('#eliminate_zero_dimensions').change(function()       { NETDATA.setOption('eliminate_zero_dimensions', $(this).prop('checked')); });
2475             $('#destroy_on_hide').change(function()                 { NETDATA.setOption('destroy_on_hide', $(this).prop('checked')); });
2476             $('#async_on_scroll').change(function()                 { NETDATA.setOption('async_on_scroll', $(this).prop('checked')); });
2477             $('#parallel_refresher').change(function()              { NETDATA.setOption('parallel_refresher', $(this).prop('checked')); });
2478             $('#concurrent_refreshes').change(function()            { NETDATA.setOption('concurrent_refreshes', $(this).prop('checked')); });
2479             $('#sync_selection').change(function()                  { NETDATA.setOption('sync_selection', $(this).prop('checked')); });
2480             $('#sync_pan_and_zoom').change(function()               { NETDATA.setOption('sync_pan_and_zoom', $(this).prop('checked')); });
2481             $('#stop_updates_when_focus_is_lost').change(function() {
2482                 urlOptions.update_always = !$(this).prop('checked');
2483                 urlOptions.hashUpdate();
2484
2485                 NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always);
2486             });
2487             $('#smooth_plot').change(function()                     { NETDATA.setOption('smooth_plot', $(this).prop('checked')); });
2488             $('#pan_and_zoom_data_padding').change(function()       { NETDATA.setOption('pan_and_zoom_data_padding', $(this).prop('checked')); });
2489             $('#show_help').change(function()                       {
2490                 urlOptions.help = $(this).prop('checked');
2491                 urlOptions.hashUpdate();
2492
2493                 NETDATA.setOption('show_help', urlOptions.help);
2494                 netdataReload();
2495             });
2496
2497             // this has to be the last
2498             // it reloads the page
2499             $('#netdata_theme_control').change(function() {
2500                 urlOptions.theme = $(this).prop('checked')?'slate':'white';
2501                 urlOptions.hashUpdate();
2502
2503                 if(setTheme(urlOptions.theme))
2504                     netdataReload();
2505             });
2506
2507             $('#updateModal').on('show.bs.modal', function() {
2508                 versionLog('checking, please wait...');
2509             });
2510
2511             $('#updateModal').on('shown.bs.modal', function() {
2512                 notifyForUpdate(true);
2513             });
2514
2515             $('#alarmsModal').on('shown.bs.modal', function() {
2516                 NETDATA.pause(alarmsUpdateModal);
2517             });
2518
2519             $('#alarmsModal').on('hidden.bs.modal', function() {
2520                 NETDATA.unpause();
2521                 document.getElementById('alarms_active').innerHTML =
2522                         document.getElementById('alarms_all').innerHTML =
2523                         document.getElementById('alarms_log').innerHTML =
2524                                 'loading...';
2525             });
2526
2527             $('#deleteRegistryModal').on('hidden.bs.modal', function() {
2528                 deleteRegistryGuid = null;
2529             });
2530
2531             if(isdemo()) {
2532                 // do not to give errors on netdata demo servers for 60 seconds
2533                 NETDATA.options.current.retries_on_data_failures = 60;
2534
2535                 if(urlOptions.nowelcome !== true) {
2536                     setTimeout(function() {
2537                         $('#welcomeModal').modal();
2538                     }, 1000);
2539                 }
2540
2541                 // google analytics when this is used for the home page of the demo sites
2542                 // this does not run on user's installations
2543                 setTimeout(function() {
2544                     (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
2545                     (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
2546                     m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
2547                     })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
2548
2549                     ga('create', 'UA-64295674-3', 'auto');
2550                     ga('send', 'pageview');
2551                 }, 2000);
2552             }
2553             else notifyForUpdate();
2554
2555             if(urlOptions.show_alarms === true)
2556                 setTimeout(function() { $('#alarmsModal').modal('show'); }, 1000);
2557
2558             var sidebar = document.getElementById('sidebar');
2559             Ps.initialize(sidebar, {
2560                 wheelSpeed: 0.5,
2561                 wheelPropagation: true,
2562                 swipePropagation: true,
2563                 minScrollbarLength: null,
2564                 maxScrollbarLength: null,
2565                 useBothWheelAxes: false,
2566                 suppressScrollX: true,
2567                 suppressScrollY: false,
2568                 scrollXMarginOffset: 0,
2569                 scrollYMarginOffset: 0,
2570                 theme: 'default'
2571             });
2572             Ps.update(sidebar);
2573
2574             var registry = document.getElementById('myNetdataDropdownUL');
2575             Ps.initialize(registry, {
2576                 wheelSpeed: 1,
2577                 wheelPropagation: false,
2578                 swipePropagation: false,
2579                 minScrollbarLength: null,
2580                 maxScrollbarLength: null,
2581                 useBothWheelAxes: false,
2582                 suppressScrollX: true,
2583                 suppressScrollY: false,
2584                 scrollXMarginOffset: 0,
2585                 scrollYMarginOffset: 0,
2586                 theme: 'default'
2587             });
2588             Ps.update(registry);
2589
2590             NETDATA.onresizeCallback = function() {
2591                 Ps.update(sidebar);
2592                 Ps.update(registry);
2593             };
2594
2595             $('#myNetdataDropdownParent')
2596                 .on('show.bs.dropdown', function () {
2597                     NETDATA.pause(function() {});
2598                 })
2599                 .on('shown.bs.dropdown', function () {
2600                     Ps.update(registry);
2601                 })
2602                 .on('hidden.bs.dropdown', function () {
2603                     NETDATA.unpause();
2604                 });
2605
2606             // var netdataEnded = performance.now();
2607             // console.log('start up time: ' + (netdataEnded - netdataStarted).toString() + ' ms');
2608         }
2609
2610         function resetDashboardOptions() {
2611             var help = NETDATA.options.current.show_help;
2612
2613             NETDATA.resetOptions();
2614             if(setTheme('slate'))
2615                 netdataReload();
2616
2617             if(help !== NETDATA.options.current.show_help)
2618                 netdataReload();
2619         }
2620
2621         // callback to add the dashboard info to the
2622         // parallel javascript downloader in netdata
2623         var netdataPrepCallback = function() {
2624             NETDATA.requiredCSS.push({
2625                 url: NETDATA.serverDefault + 'css/bootstrap-toggle-2.2.2.min.css',
2626                 isAlreadyLoaded: function() { return false; }
2627             });
2628
2629             NETDATA.requiredJs.push({
2630                 url: NETDATA.serverDefault + 'lib/bootstrap-toggle-2.2.2.min.js',
2631                 isAlreadyLoaded: function() { return false; }
2632             });
2633
2634             NETDATA.requiredJs.push({
2635                 url: NETDATA.serverDefault + 'dashboard_info.js?v20170115-1',
2636                 async: false,
2637                 isAlreadyLoaded: function() { return false; }
2638             });
2639
2640             if(isdemo()) {
2641                 document.getElementById('masthead').style.display = 'block';
2642             }
2643             else {
2644                 if(urlOptions.update_always === true)
2645                     NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always);
2646             }
2647         };
2648
2649         // our entry point
2650         // var netdataStarted = performance.now();
2651         var netdataCallback = initializeDynamicDashboard;
2652     </script>
2653 </head>
2654
2655 <body data-spy="scroll" data-target="#sidebar">
2656     <div id="loadOverlay" class="loadOverlay" style="background-color: #888; color: #888;">
2657         netdata<br/><div style="font-size: 3vh;">Real-time performance monitoring, done right!</div>
2658     </div>
2659     <script type="text/javascript">
2660         // change the loadOverlay colors ASAP to match the theme
2661         document.getElementById('loadOverlay').style = (urlOptions.theme === 'slate')?"background-color:#272b30; color: #373b40;":"background-color:#fff; color: #ddd;";
2662     </script>
2663     <nav class="navbar navbar-default navbar-fixed-top" role="banner">
2664         <div class="container">
2665             <nav id="mynetdata_nav" class="collapse navbar-collapse navbar-left hidden-sm hidden-xs" role="navigation" style="padding-right: 20px;">
2666                 <ul class="nav navbar-nav">
2667                     <li class="dropdown" id="myNetdataDropdownParent">
2668                         <a href="#" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a>
2669                         <ul class="dropdown-menu scrollable-menu inpagemenu multi-column columns-2" role="menu" id="myNetdataDropdownUL">
2670                             <div class="row">
2671                                 <div class="col-sm-6" style="width: 85%; padding-right: 0;">
2672                                     <ul id="mynetdata_servers" class="multi-column-dropdown">
2673                                         <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li>
2674                                     </ul>
2675                                 </div>
2676                                 <div class="col-sm-3 hidden-xs" style="width: 15%; padding-left: 0;">
2677                                     <ul id="mynetdata_actions1" class="multi-column-dropdown">
2678                                     <li style="color: #999;">&nbsp;</li>
2679                                     </ul>
2680                                 </div>
2681                             </div>
2682                         </ul>
2683                     </li>
2684                 </ul>
2685             </nav>
2686             <div class="navbar-header">
2687                 <button class="navbar-toggle" type="button" data-toggle="collapse" data-target=".navbar-collapse">
2688                     <span class="sr-only">Toggle navigation</span>
2689                     <span class="icon-bar"></span>
2690                     <span class="icon-bar"></span>
2691                     <span class="icon-bar"></span>
2692                 </button>
2693                 <a href="/" class="navbar-brand" id="hostname" title="reload the dashboard">netdata</a>
2694             </div>
2695             <nav class="collapse navbar-collapse navbar-right" role="navigation">
2696                 <ul class="nav navbar-nav">
2697                     <li><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal" title="alarms"><i class="fa fa-bell"></i>&nbsp;<span class="hidden-sm">Alarms&nbsp;</span><span id="alarms_count_badge" class="badge"></span></a></li>
2698                     <li><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal" title="dashboard settings"><i class="fa fa-sliders"></i>&nbsp;<span class="hidden-sm">Settings</span></a></li>
2699                     <li class="hidden-sm" id="updateButton"><a href="#" class="btn" data-toggle="modal" data-target="#updateModal" title="check for update"><i class="fa fa-cloud-download"></i> <span class="hidden-sm hidden-md">Update </span><span id="update_badge" class="badge"></span></a></li>
2700                     <li><a href="https://github.com/firehol/netdata/wiki" class="btn" target="_blank" title="netdata on github"><i class="fa fa-github"></i></a></li>
2701                     <li><a href="https://twitter.com/linuxnetdata" class="btn" target="_blank" title="netdata on twitter"><i class="fa fa-twitter" aria-hidden="true"></i></a></li>
2702                     <li><a href="https://www.facebook.com/linuxnetdata/" class="btn" target="_blank" title="netdata on facebook"><i class="fa fa-facebook-official" aria-hidden="true"></i></a></li>
2703                     <li class="hidden-sm"><a href="#" class="btn" data-toggle="modal" data-target="#helpModal" title="dashboard help"><i class="fa fa-question-circle"></i>&nbsp;<span class="hidden-sm hidden-md">Help</span></a></li>
2704                     <li class="dropdown hidden-sm hidden-md hidden-lg">
2705                         <a href="#" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a>
2706                         <ul id="mynetdata_servers2" class="dropdown-menu scrollable-menu inpagemenu" role="menu">
2707                             <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li>
2708                         </ul>
2709                     </li>
2710                 </ul>
2711             </nav>
2712         </div>
2713     </nav>
2714
2715     <div id="masthead" style="display: none;">
2716         <div class="container">
2717             <div class="row">
2718                 <div class="col-md-7">
2719                     <h1>Netdata
2720                         <p class="lead">Real-time performance monitoring, in the greatest possible detail</p>
2721                     </h1>
2722                 </div>
2723                 <div class="col-md-5">
2724                     <div class="well well-lg">
2725                         <div class="row">
2726                         <div class="col-md-6">
2727                             <b>Drag</b> charts to pan.
2728                             <b>Shift + wheel</b> on them, to zoom in and out.
2729                             <b>Double-click</b> on them, to reset.
2730                             <b>Hover</b> on them too!
2731                             </div>
2732                         <div class="col-md-6">
2733                             <div data-netdata="system.intr" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dygraph-type="line" data-dygraph-strokewidth="3" data-dygraph-smooth="true" data-dygraph-highlightcirclesize="6" data-after="-90" data-height="60px" data-colors="#C66"></div>
2734                             </div>
2735                         </div>
2736                     </div>
2737                 </div>
2738             </div>
2739         </div>
2740     </div>
2741
2742     <div class="container">
2743         <div class="row">
2744             <div class="charts-body" role="main">
2745                 <div id="charts_div"></div>
2746             </div>
2747             <div class="sidebar-body hidden-xs hidden-sm" id="sidebar-body" role="complementary">
2748                 <nav class="dashboard-sidebar hidden-print hidden-xs hidden-sm" id="sidebar" role="menu"></nav>
2749             </div>
2750         </div>
2751     </div>
2752
2753     <div id="footer" class="container" style="display: none;">
2754         <div class="row">
2755             <div class="col-md-10" role="main">
2756                 <div class="p">
2757                     <big><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></big><br/>
2758                     <i class="fa fa-copyright"></i> Copyright 2017, Costa Tsaousis.<br/>
2759                     Released under <a href="http://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">GPL v3 or later</a>.<br/>
2760                 </div>
2761                 <div class="p">
2762                     <small>
2763                         <a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a> re-distributes these software tools:
2764
2765                         <i class="fa fa-circle"></i> The excellent <a href="http://dygraphs.com/" target="_blank">Dygraphs.com</a> web chart library,
2766                         <i class="fa fa-copyright"></i> Copyright 2009, Dan Vanderkam, <a href="http://dygraphs.com/legal.html" target="_blank">MIT License</a>
2767
2768                         <i class="fa fa-circle"></i> <a href="https://rendro.github.io/easy-pie-chart/" target="_blank">Easy Pie Chart</a> web chart library,
2769                         <i class="fa fa-copyright"></i> Copyright 2013, Robert Fleischmann, <a href="https://github.com/rendro/easy-pie-chart/blob/master/LICENSE" target="_blank">MIT License</a>
2770
2771                         <i class="fa fa-circle"></i> <a href="http://bernii.github.io/gauge.js/" target="_blank">Gauge.js</a> web chart library,
2772                         <i class="fa fa-copyright"></i> Copyright, Bernard Kobos, <a href="http://bernii.github.io/gauge.js/" target="_blank">MIT License</a>
2773
2774                         <i class="fa fa-circle"></i> <a href="https://jquery.org/" target="_blank">jQuery</a>,
2775                         <i class="fa fa-copyright"></i> Copyright 2015, jQuery Foundation, <a href="https://jquery.org/license/" target="_blank">MIT License</a>
2776
2777                         <i class="fa fa-circle"></i> <a href="http://getbootstrap.com/getting-started/" target="_blank">Bootstrap</a>,
2778                         <i class="fa fa-copyright"></i> Copyright 2015, Twitter, <a href="http://getbootstrap.com/getting-started/#license-faqs" target="_blank">MIT License</a>
2779
2780                         <i class="fa fa-circle"></i> <a href="http://www.bootstraptoggle.com/" target="_blank">Bootstrap Toggle</a>,
2781                         <i class="fa fa-copyright"></i> Copyright (c) 2011-2014 Min Hur, The New York Times Company, <a href="https://github.com/minhur/bootstrap-toggle/blob/master/LICENSE" target="_blank">MIT License</a>
2782
2783                         <i class="fa fa-circle"></i> <a href="https://github.com/noraesae/perfect-scrollbar" target="_blank">perfect-scrollbar</a>,
2784                         <i class="fa fa-copyright"></i> Copyright 2016, Hyunje Alex Jun and other contributors, <a href="https://github.com/noraesae/perfect-scrollbar/blob/master/LICENSE" target="_blank">MIT License</a>
2785
2786                         <i class="fa fa-circle"></i> <a href="https://fortawesome.github.io/Font-Awesome/" target="_blank">FontAwesome</a>,
2787                         <i class="fa fa-copyright"></i> Created by Dave Gandy, Font: <a href="http://scripts.sil.org/OFL" target="_blank">SIL OFL 1.1 License</a>, CSS: <a href="http://opensource.org/licenses/mit-license.html" target="_blank">MIT License</a>
2788
2789                         <i class="fa fa-circle"></i> <a href="http://www.iconsdb.com/soylent-red-icons/seo-performance-icon.html" target="_blank">IconsDB.com Icons</a>, Icons provided as CC0 1.0 Universal (CC0 1.0) Public Domain Dedication.
2790
2791                         <i class="fa fa-circle"></i> <a href="http://bootstrap-table.wenzhixin.net.cn/" target="_blank">bootstrap-table</a>,
2792                         <i class="fa fa-copyright"></i> Copyright (c) 2012-2016 Zhixin Wen, <a href="https://github.com/wenzhixin/bootstrap-table/blob/master/LICENSE" target="_blank">MIT License</a>
2793
2794                         <i class="fa fa-circle"></i> <a href="https://github.com/hhurz/tableExport.jquery.plugin" target="_blank">tableExport.jquery.plugin</a>,
2795                         <i class="fa fa-copyright"></i> Copyright (c) 2015,2016 hhurz, <a href="http://rawgit.com/hhurz/tableExport.jquery.plugin/master/tableExport.js" target="_blank">MIT License</a>
2796
2797                     </small>
2798                 </div>
2799             </div>
2800         </div>
2801     </div>
2802
2803     <div class="modal fade" id="welcomeModal" tabindex="-1" role="dialog" aria-labelledby="welcomeModalLabel">
2804         <div class="modal-dialog modal-lg" role="document">
2805             <div class="modal-content">
2806                 <div class="modal-header">
2807                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2808                     <h4 class="modal-title" id="welcomeModalLabel">Welcome to the world of netdata</h4>
2809                 </div>
2810                 <div class="modal-body">
2811                     <div class="p">
2812                         <div style="width: 100%; text-align: center; padding-top: 10px; padding-bottom: 10px; font-size: 18px;">
2813                             if there is a metric for something, we want it visualised<br/>
2814                             and we want this visualisation to be <strong>real-time</strong>, <strong>efficient</strong> and <strong>awesome</strong>
2815                         </div>
2816                     </div>
2817                     <div class="p">
2818                         <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>
2819                         is a new way to monitor your systems and applications, to get <strong>real-time insights</strong>
2820                         of what is really happening and what affects performance.
2821                         It is carefully optimised to be a real-time system, without interfering in any way,
2822                         to the core function of your systems.
2823                     </div>
2824                     <div class="p">
2825                         <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>
2826                         has been designed to monitor <strong>massive amounts of metrics, per server, per second</strong>.
2827                         When installed, it might come up with 1k to 3k metrics, but we have been testing it with 100k
2828                         metrics, all collected per second, and still the cpu utilisation remained negligible.
2829                         <br/>
2830                         We have also tried to give each metric, a meaning, a context.
2831                         We have grouped and categorized all metrics into meaningful charts, providing a
2832                         better understanding of the underlying technologies and mechanisms.
2833                     </div>
2834                     <div class="p">
2835                         <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> is free,
2836                         open-source software. If you decide to use it,
2837                         <strong><a href="https://github.com/firehol/netdata/wiki/a-github-star-is-important" target="_blank">it is important to give netdata a star at GitHub</a></strong>.
2838                     </div>
2839                     <div class="p">
2840                         Enjoy real-time performance monitoring!
2841                     </div>
2842                     <div class="p">
2843                         Costa Tsaousis
2844                     </div>
2845                 </div>
2846                 <div class="modal-footer">
2847                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2848                 </div>
2849             </div>
2850         </div>
2851     </div>
2852
2853     <div class="modal fade" id="helpModal" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel">
2854         <div class="modal-dialog modal-lg" role="document">
2855             <div class="modal-content">
2856                 <div class="modal-header">
2857                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2858                     <h4 class="modal-title" id="helpModalLabel">Dashboard Help</h4>
2859                 </div>
2860                 <div class="modal-body">
2861
2862                     <h4>Dygraphs (line, area and stacked area charts)</h4>
2863
2864                     <!-- Nav tabs -->
2865                     <ul class="nav nav-tabs" role="tablist">
2866                         <li role="presentation" class="active"><a href="#help_mouse" aria-controls="help_mouse" role="tab" data-toggle="tab">Mouse Interface</a></li>
2867                         <li role="presentation"><a href="#help_touch" aria-controls="help_touch" role="tab" data-toggle="tab">Touch Interface</a></li>
2868                     </ul>
2869
2870                     <!-- Tab panes -->
2871                     <div class="tab-content">
2872                         <div role="tabpanel" class="tab-pane active" id="help_mouse">
2873                             <div class="p">
2874                                 <h4>Mouse Over / Hover</h4>
2875                                 Mouse over on a chart to show, at its legend, the values for the timestamp under the mouse (the chart will also highlight the point at the chart).
2876                                 <br/>
2877                                 All the other visible charts will also show and highlight their values for the same timestamp.
2878                             </div>
2879                             <hr/>
2880                             <div class="p">
2881                                 <h4>Drag Chart Contents</h4>
2882                                 Drag the contents of a chart to pan it horizontally.
2883                                 <br/>
2884                                 All the charts will follow soon after you let the chart alone (this little delay is by design: it speeds up your browser and lets you focus on what you are exploring).
2885                                 <br/>
2886                                 Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double click</b> a panned chart.
2887                             </div>
2888                             <hr/>
2889                             <div class="p">
2890                                 <h4>Double Click</h4>
2891                                 Double Click a chart to reset all the charts to their default auto-refreshing state.
2892                             </div>
2893                             <hr/>
2894                             <div class="p">
2895                                 <h4>SHIFT + Drag</h4>
2896                                 While pressing the shift key, click on the contents of a chart and move the mouse to select an area, to zoom in. The other charts will follow too. Zooming is performed in two phases:
2897                                 <ul>
2898                                     <li>The already loaded chart contents are zoomed (low resolution)</li>
2899                                     <li>New data are transferred from the netdata server, to refresh the chart with possibly more detail.</li>
2900                                 </ul>
2901                                 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
2902                             </div>
2903                             <hr/>
2904                             <div class="p">
2905                                 <h4>SHIFT + Mouse Wheel</h4>
2906                                 While pressing the shift key and the mouse pointer is over the contents of a chart, scroll the mouse wheel to zoom in or out. This kind of zooming is aligned to center below the mouse pointer. The other charts will follow too.
2907                                 <br/>
2908                                 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
2909                             </div>
2910                             <hr/>
2911                             <div class="p">
2912                                 <h4>Legend Operations</h4>
2913                                 Click on the label or value of a dimension, will select / un-select this dimension.
2914                                 <br/>
2915                                 You can press any of the SHIFT or CONTROL keys and then click on legend labels or values, to select / un-select multiple dimensions.
2916                             </div>
2917                         </div>
2918                         <div role="tabpanel" class="tab-pane" id="help_touch">
2919                             <div class="p">
2920                                 <h4>Single Tap</h4>
2921                                 Single Tap on the contents of a chart to show, at its legend, the values for the timestamp tapped (the chart will also highlight the point at the chart).
2922                                 <br/>
2923                                 All the other visible charts will also show and highlight their values for the same timestamp.
2924                             </div>
2925                             <hr/>
2926                             <div class="p">
2927                                 <h4>Drag Chart Contents</h4>
2928                                 Touch and Drag the contents of a chart to pan it horizontally.
2929                                 <br/>
2930                                 All the charts will follow soon after you let the chart alone (this little delay is by design: it speeds up your browser and lets you focus on what you are exploring).
2931                                 <br/>
2932                                 Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double tap</b> a panned chart.
2933                             </div>
2934                             <hr/>
2935                             <div class="p">
2936                                 <h4>Double Tap</h4>
2937                                 Double tap a chart to reset all the charts to their default auto-refreshing state.
2938                             </div>
2939                             <hr/>
2940                             <div class="p">
2941                                 <h4>Zoom <small>(does not work on firefox and IE/Edge)</small></h4>
2942                                 With two fingers, zoom in or out.
2943                                 <br/>
2944                                 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
2945                             </div>
2946                             <hr/>
2947                             <div class="p">
2948                                 <h4>Legend Operations</h4>
2949                                 Tap on the label or value of a dimension, will select / un-select this dimension.
2950                             </div>
2951                         </div>
2952                     </div>
2953                 </div>
2954                 <div class="modal-footer">
2955                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2956                 </div>
2957             </div>
2958         </div>
2959     </div>
2960
2961     <div class="modal fade" id="alarmsModal" tabindex="-1" role="dialog" aria-labelledby="alarmsModalLabel">
2962         <div class="modal-dialog modal-lg" role="document"  style="display: table;"> <!-- allow the modal to expand horizontally -->
2963             <div class="modal-content">
2964                 <div class="modal-header">
2965                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2966                     <h4 class="modal-title" id="alarmsModalLabel">netdata alarms</h4>
2967                 </div>
2968                 <div class="modal-body">
2969                     <!-- Nav tabs -->
2970                     <ul class="nav nav-tabs" role="tablist">
2971                         <li role="presentation" class="active"><a href="#alarms_active" aria-controls="alarms_active" role="tab" data-toggle="tab">Active</a></li>
2972                         <li role="presentation"><a href="#alarms_all" aria-controls="alarms_all" role="tab" data-toggle="tab">All</a></li>
2973                         <li role="presentation"><a href="#alarms_log" aria-controls="alarms_log" role="tab" data-toggle="tab">Log</a></li>
2974                     </ul>
2975
2976                     <!-- Tab panes -->
2977                     <div class="tab-content">
2978                         <div role="tabpanel" class="tab-pane active" id="alarms_active">
2979                             loading...
2980                         </div>
2981                         <div role="tabpanel" class="tab-pane" id="alarms_all">
2982                             loading...
2983                         </div>
2984                         <div role="tabpanel" class="tab-pane" id="alarms_log">
2985                             loading...
2986                         </div>
2987                     </div>
2988                 </div>
2989                 <div class="modal-footer">
2990                     <!-- <a href="#" onclick="alarmsUpdateModal(); return false;" type="button" class="btn btn-default">Update</a> -->
2991                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2992                 </div>
2993             </div>
2994         </div>
2995     </div>
2996
2997     <div class="modal fade" id="optionsModal" tabindex="-1" role="dialog" aria-labelledby="optionsModalLabel">
2998         <div class="modal-dialog modal-lg" role="document">
2999             <div class="modal-content">
3000                 <div class="modal-header">
3001                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
3002                     <h4 class="modal-title" id="optionsModalLabel">netdata dashboard options</h4>
3003                 </div>
3004                 <div class="modal-body">
3005                     <center>
3006                         <small style="color: #BBBBBB;">These are browser settings. Each viewer has its own. They do not affect the operation of your netdata server.
3007                         <br/>
3008                         Settings take effect immediately and are saved permanently to browser local storage (except the refresh on focus / always option).
3009                         <br/>
3010                         To reset all options (including charts sizes) to their defaults, click <a href="#" onclick="resetDashboardOptions(); return false;">here</a>.</small>
3011                     </center>
3012                     <div style="padding: 10px;"></div>
3013
3014                     <!-- Nav tabs -->
3015                     <ul class="nav nav-tabs" role="tablist">
3016                         <li role="presentation" class="active"><a href="#settings_performance" aria-controls="settings_performance" role="tab" data-toggle="tab">Performance</a></li>
3017                         <li role="presentation"><a href="#settings_sync" aria-controls="settings_sync" role="tab" data-toggle="tab">Synchronization</a></li>
3018                         <li role="presentation"><a href="#settings_visual" aria-controls="settings_visual" role="tab" data-toggle="tab">Visual</a></li>
3019                     </ul>
3020
3021                     <!-- Tab panes -->
3022                     <div class="tab-content">
3023                         <div role="tabpanel" class="tab-pane active" id="settings_performance">
3024                             <form id="optionsForm1" method="get" class="form-horizontal">
3025                                 <div class="form-group">
3026                                     <table>
3027                                     <tr class="option-row">
3028                                         <td class="option-control"><input id="stop_updates_when_focus_is_lost" type="checkbox" checked data-toggle="toggle" data-offstyle="danger" data-onstyle="success" data-on="On Focus" data-off="Always" data-width="110px"></td>
3029                                         <td class="option-info"><strong>When to refresh the charts?</strong><br/>
3030                                             <small>When set to <b>On Focus</b>, the charts will stop being updated if the page / tab does not have the focus of the user. When set to <b>Always</b>, the charts will always be refreshed. Set it to <b>On Focus</b> it to lower the CPU requirements of the browser (and extend the battery of laptops and tablets) when this page does not have your focus. Set to <b>Always</b> to work on another window (i.e. change the settings of something) and have the charts auto-refresh in this window.</small>
3031                                         </td>
3032                                         </tr>
3033                                     <tr class="option-row">
3034                                         <td class="option-control">
3035                                         <input id="eliminate_zero_dimensions" type="checkbox" checked data-toggle="toggle" data-on="Non Zero" data-off="All" data-width="110px">
3036                                         </td>
3037                                         <td class="option-info"><strong>Which dimensions to show?</strong><br/>
3038                                             <small>When set to <b>Non Zero</b>, dimensions that have all their values (within the current view) set to zero will not be transferred from the netdata server (except if all dimensions of the chart are zero, in which case this setting does nothing - all dimensions are transferred and shown). When set to <b>All</b>, all dimensions will always be shown. Set it to <b>Non Zero</b> to lower the data transferred between netdata and your browser, lower the CPU requirements of your browser (fewer lines to draw) and increase the focus on the legends (fewer entries at the legends).</small>
3039                                         </td>
3040                                         </tr>
3041                                     <tr class="option-row">
3042                                         <td class="option-control"><input id="destroy_on_hide" type="checkbox" data-toggle="toggle" data-on="Destroy" data-off="Hide" data-width="110px"></td>
3043                                         <td class="option-info"><strong>How to handle hidden charts?</strong><br/>
3044                                             <small>When set to <b>Destroy</b>, charts that are not in the current viewport of the browser (are above, or below the visible area of the page), will be destroyed and re-created if and when they become visible again. When set to <b>Hide</b>, the not-visible charts will be just hidden, to simplify the DOM and speed up your browser. Set it to <b>Destroy</b>, to lower the memory requirements of your browser. Set it to <b>Hide</b> for faster restoration of charts on page scrolling.</small>
3045                                         </td>
3046                                         </tr>
3047                                     <tr class="option-row">
3048                                         <td class="option-control"><input id="async_on_scroll" type="checkbox" data-toggle="toggle" data-on="Async" data-off="Sync" data-width="110px"></td>
3049                                         <td class="option-info"><strong>Page scroll handling?</strong><br/>
3050                                             <small>When set to <b>Sync</b>, charts will be examined for their visibility synchronously. On slow computers this may impact the smoothness of page scrolling. To work asynchronously set it to <b>Async</b>. When set to <b>Sync</b>, the performance of page scrolling is monitored and this setting switches automatically to <b>Async</b> if the browser is found slow. Set it to <b>Sync</b> for best visual experience. Set it to <b>Async</b> for smoother page scrolling.</small>
3051                                         </td>
3052                                         </tr>
3053                                     </table>
3054                                 </div>
3055                             </form>
3056                         </div>
3057                         <div role="tabpanel" class="tab-pane" id="settings_sync">
3058                             <form id="optionsForm2" method="get" class="form-horizontal">
3059                                 <div class="form-group">
3060                                     <table>
3061                                     <tr class="option-row">
3062                                         <td class="option-control"><input id="parallel_refresher" type="checkbox" checked data-toggle="toggle" data-on="Parallel" data-off="Sequential" data-width="110px"></td>
3063                                         <td class="option-info"><strong>Which chart refresh policy to use?</strong><br/>
3064                                             <small>When set to <b>parallel</b>, visible charts are refreshed in parallel (all queries are sent to netdata server in parallel) and are rendered asynchronously. When set to <b>sequential</b> charts are refreshed one after another. Set it to parallel if your browser can cope with it (most modern browsers do), set it to sequential if you work on an older/slower computer.</small>
3065                                         </td>
3066                                     </tr>
3067                                     <tr class="option-row" id="concurrent_refreshes_row">
3068                                         <td class="option-control"><input id="concurrent_refreshes" type="checkbox" checked data-toggle="toggle" data-on="Resync" data-off="Best Effort" data-width="110px"></td>
3069                                         <td class="option-info"><strong>Shall we re-sync chart refreshes?</strong><br/>
3070                                             <small>When set to <b>Resync</b>, the dashboard will attempt to re-synchronize all the charts so that they are refreshed concurrently. When set to <b>Best Effort</b>, each chart may be refreshed with a little time difference to the others. Normally, the dashboard starts refreshing them in parallel, but depending on the speed of your computer and the network latencies, charts start having a slight time difference. Setting this to <b>Resync</b> will attempt to re-synchronize the charts on every update. Setting it to <b>Best Effort</b> may lower the pressure on your browser and the network.</small>
3071                                         </td>
3072                                     </tr>
3073                                     <tr class="option-row">
3074                                         <td class="option-control"><input id="sync_selection" type="checkbox" checked data-toggle="toggle" data-on="Sync" data-off="Don't Sync" data-onstyle="success" data-offstyle="danger" data-width="110px"></td>
3075                                         <td class="option-info"><strong>Sync hover selection on all charts?</strong><br/>
3076                                             <small>When enabled, a selection on one chart will automatically select the same time on all other visible charts and the legends of all visible charts will be updated to show the selected values. When disabled, only the chart getting the user's attention will be selected. Enable it to get better insights of the data. Disable it if you are on a very slow computer that cannot actually do it.</small>
3077                                         </td>
3078                                         </tr>
3079                                     <tr class="option-row">
3080                                         <td class="option-control"><input id="sync_pan_and_zoom" type="checkbox" checked data-toggle="toggle"  data-on="Sync" data-off="Don't Sync" data-onstyle="success" data-offstyle="danger" data-width="110px"></td>
3081                                         <td class="option-info"><strong>Sync pan and zoom on all charts?</strong><br/>
3082                                             <small>When enabled, pan and zoom operations on a chart will be replicated to all charts (even the ones that are not currently visible - of course only when they will become visible). When disabled, pan and zoom operations will not be propagated to other charts.</small>
3083                                         </td>
3084                                         </tr>
3085                                     </table>
3086                                 </div>
3087                             </form>
3088                         </div>
3089                         <div role="tabpanel" class="tab-pane" id="settings_visual">
3090                             <form id="optionsForm3" method="get" class="form-horizontal">
3091                                 <div class="form-group">
3092                                     <table>
3093                                     <tr class="option-row">
3094                                         <td class="option-control"><input id="netdata_theme_control" type="checkbox" checked data-toggle="toggle" data-offstyle="danger" data-onstyle="success" data-on="Dark" data-off="White" data-width="110px"></td>
3095                                         <td class="option-info"><strong>Which theme to use?</strong><br/>
3096                                             <small>Netdata comes with two themes: <b>Dark</b> (the default) and <b>White</b>.
3097                                             <br/>
3098                                             <b>Switching this will reload the dashboard</b>.
3099                                             </small>
3100                                         </td>
3101                                         </tr>
3102                                     <tr class="option-row">
3103                                         <td class="option-control"><input id="show_help" type="checkbox" checked data-toggle="toggle" data-on="Help Me" data-off="No Help" data-width="110px"></td>
3104                                         <td class="option-info"><strong>Do you need help?</strong><br/>
3105                                             <small>Netdata can show some help in some areas to help you use the dashboard. If all these balloons bother you, disable them using this switch.
3106                                             <br/>
3107                                             <b>Switching this will reload the dashboard</b>.
3108                                             </small>
3109                                         </td>
3110                                         </tr>
3111                                     <tr class="option-row">
3112                                         <td class="option-control"><input id="pan_and_zoom_data_padding" type="checkbox" checked data-toggle="toggle"  data-on="Pad" data-off="Don't Pad" data-width="110px"></td>
3113                                         <td class="option-info"><strong>Enable data padding when panning and zooming?</strong><br/>
3114                                             <small>When set to <b>Pad</b> the charts will be padded with more data, both before and after the visible area, thus giving the impression the whole database is loaded. This padding will happen only after the first pan or zoom operation on the chart (initially all charts have only the visible data). When set to <b>Don't Pad</b> only the visible data will be transfered from the netdata server, even after the first pan and zoom operation.</small>
3115                                         </td>
3116                                         </tr>
3117                                     <tr class="option-row">
3118                                         <td class="option-control"><input id="smooth_plot" type="checkbox" checked data-toggle="toggle"  data-on="Smooth" data-off="Rough" data-width="110px"></td>
3119                                         <td class="option-info"><strong>Enable Bézier lines on charts?</strong><br/>
3120                                             <small>When set to <b>Smooth</b> the charts libraries that support it, will plot smooth curves instead of simple straight lines to connect the points.
3121                                             <br/>
3122                                             Keep in mind <a href="http://dygraphs.com" target="_blank">dygraphs</a>, the main charting library in netdata dashboards, can only smooth line charts. It cannot smooth area or stacked charts. When set to <b>Rough</b>, this setting can lower the CPU resources consumed by your browser.</small>
3123                                         </td>
3124                                         </tr>
3125                                     </table>
3126                                 </div>
3127                             </form>
3128                         </div>
3129                     </div>
3130                 </div>
3131                 <div class="modal-footer">
3132                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3133                 </div>
3134             </div>
3135         </div>
3136     </div>
3137
3138
3139     <div class="modal fade" id="updateModal" tabindex="-1" role="dialog" aria-labelledby="updateModalLabel">
3140         <div class="modal-dialog" role="document">
3141             <div class="modal-content">
3142                 <div class="modal-header">
3143                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
3144                     <h4 class="modal-title" id="updateModalLabel">Update Check</h4>
3145                 </div>
3146                 <div class="modal-body">
3147                     Your netdata version: <b><code><span id="netdataVersion">Unknown</span></code></b>
3148                     <br/>
3149                     <div style="padding: 10px;"></div>
3150                     <div id="versionCheckLog">Not checked yet. Please press the Check Now button.</div>
3151                     <div>
3152                         <hr/>
3153                     </div>
3154                     <div>
3155                         For progress reports and key netdata updates: <strong><a href="https://twitter.com/linuxnetdata" target="_blank">follow netdata on <i class="fa fa-twitter" aria-hidden="true"></i> twitter</a></strong>.
3156                         <br/>
3157                         <small>
3158                             You can also <a href="https://www.facebook.com/linuxnetdata/" target="_blank">follow netdata on <i class="fa fa-facebook" aria-hidden="true"></i> facebook</a>,
3159                             or <a href="https://github.com/firehol/netdata" target="_blank">watch netdata on <i class="fa fa-github" aria-hidden="true"></i> github</a>.
3160                         </small>
3161                     </div>
3162                 </div>
3163                 <div class="modal-footer">
3164                     <a href="#" onclick="notifyForUpdate(true); return false;" type="button" class="btn btn-default">Check Now</a>
3165                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3166                 </div>
3167             </div>
3168         </div>
3169     </div>
3170
3171     <div class="modal fade" id="deleteRegistryModal" tabindex="-1" role="dialog" aria-labelledby="deleteRegistryModalLabel">
3172         <div class="modal-dialog" role="document">
3173             <div class="modal-content">
3174                 <div class="modal-header">
3175                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
3176                     <h4 class="modal-title" id="deleteRegistryModalLabel">Delete <span id="deleteRegistryServerName"></span>?</h4>
3177                 </div>
3178                 <div class="modal-body">
3179                     You are about to delete, from your personal list of netdata servers, the following server:
3180                     <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;">
3181                     <b><span id="deleteRegistryServerName2"></span></b>
3182                     <br/>
3183                     <b><span id="deleteRegistryServerURL"></span></b>
3184                     </p>
3185                     Are you sure you want to do this?
3186                     <br/>
3187                     <div style="padding: 10px;"></div>
3188                     <small>Keep in mind, this server will be added back if and when you visit it again.</small>
3189                     <br/>
3190                     <div id="deleteRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
3191                 </div>
3192                 <div class="modal-footer">
3193                     <button type="button" class="btn btn-success" data-dismiss="modal">keep it</button>
3194                     <a href="#" onclick="notifyForDeleteRegistry(true); return false;" type="button" class="btn btn-danger">delete it</a>
3195                 </div>
3196             </div>
3197         </div>
3198     </div>
3199
3200     <div class="modal fade" id="switchRegistryModal" tabindex="-1" role="dialog" aria-labelledby="switchRegistryModalLabel">
3201         <div class="modal-dialog" role="document">
3202             <div class="modal-content">
3203                 <div class="modal-header">
3204                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
3205                     <h4 class="modal-title" id="switchRegistryModalLabel">Switch Netdata Registry Identity</h4>
3206                 </div>
3207                 <div class="modal-body">
3208                     You can copy and paste the following ID to all your browsers (e.g. work and home).
3209                     <br/>
3210                     All the browsers with the same ID will identify <b>you</b>, so please don't share this with others.
3211                     <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;">
3212                         <form action="#">
3213                             <input type="text" class="form-control" id="switchRegistryPersonGUID" placeholder="your personal ID" maxlength="36" autocomplete="off" style="text-align: center; font-size: 1.4em;">
3214                         </form>
3215                     </p>
3216                     Either copy this ID and paste it to another browser, or paste here the ID you have taken from another browser.
3217                     <p style="padding-top: 10px;"><small>
3218                         Keep in mind that:
3219                         <ul>
3220                             <li>when you switch ID, your previous ID will be lost forever - this is irreversible.</li>
3221                             <li>both IDs (your old and the new) must list this netdata at their personal lists.</li>
3222                             <li>both IDs have to be known by the registry: <b><span id="switchRegistryURL"></span></b>.</li>
3223                             <li>to get a new ID, just clear your browser cookies.</li>
3224                         </ul>
3225                     </small></p>
3226                     <div id="switchRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
3227                 </div>
3228                 <div class="modal-footer">
3229                     <button type="button" class="btn btn-success" data-dismiss="modal">cancel</button>
3230                     <a href="#" onclick="notifyForSwitchRegistry(true); return false;" type="button" class="btn btn-danger">impersonate</a>
3231                 </div>
3232             </div>
3233         </div>
3234     </div>
3235
3236     <div class="modal fade" id="gotoServerModal" tabindex="-1" role="dialog" aria-labelledby="gotoServerModalLabel">
3237         <div class="modal-dialog" role="document">
3238             <div class="modal-content">
3239                 <div class="modal-header">
3240                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
3241                     <h4 class="modal-title" id="gotoServerModalLabel"><span id="gotoServerName"></span></h4>
3242                 </div>
3243                 <div class="modal-body">
3244                     Checking known URLs for this server...
3245                     <div  style="padding-top: 20px;">
3246                         <table id="gotoServerList">
3247                         </table>
3248                     </div>
3249                     <p style="padding-top: 10px;"><small>
3250                         Checks may fail if you are viewing an HTTPS page and the server to be checked is HTTP only.
3251                     </small></p>
3252                     <div id="gotoServerResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
3253                 </div>
3254                 <div class="modal-footer">
3255                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3256                 </div>
3257             </div>
3258         </div>
3259     </div>
3260 </body>
3261 </html>
3262 <script type="text/javascript" src="dashboard.js?v20170118-11"></script>