]> arthur.barton.de Git - netdata.git/blob - web/index.html
Merge remote-tracking branch 't-h-e/master'
[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                     if(typeof(chart) === 'undefined') {
1566                         // this means the charts loaded are incomplete
1567                         // probably netdata was restarted and more charts
1568                         // are now available.
1569                         return '';
1570                     }
1571
1572                     var has_alarm = ((typeof alarm.warn !== 'undefined' || typeof alarm.crit !== 'undefined')?true:false);
1573
1574                     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;'));
1575
1576                     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>'
1577                         + '<td><table class="table">'
1578                         + ((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>'):'')
1579                         + ((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>'):'');
1580
1581                     if(full === true) {
1582                         var units = chart.units;
1583                         if(units === '%') units = '&#37;';
1584
1585                         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>'):'')
1586                             + ((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>'):'')
1587                             + ((chart.green !== null)?('<tr><td width="10%" style="text-align:right">green&nbsp;threshold</td><td><code>' + chart.green + ' ' + units + '</code></td></tr>'):'')
1588                             + ((chart.red !== null)?('<tr><td width="10%" style="text-align:right">red&nbsp;threshold</td><td><code>' + chart.red + ' ' + units + '</code></td></tr>'):'');
1589                     }
1590
1591                     var delay = '';
1592                     if((alarm.delay_up_duration > 0 || alarm.delay_down_duration > 0) && alarm.delay_multiplier != 0 && alarm.delay_max_duration > 0) {
1593                         if(alarm.delay_up_duration == alarm.delay_down_duration) {
1594                             delay += '<small><br/>hysteresis ' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' });
1595                         }
1596                         else {
1597                             delay = '<small><br/>hysteresis ';
1598                             if(alarm.delay_up_duration > 0) {
1599                                 delay += 'on&nbsp;escalation&nbsp;<code>' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' }) + '</code>, ';
1600                             }
1601                             if(alarm.delay_down_duration > 0) {
1602                                 delay += 'on&nbsp;recovery&nbsp;<code>' + seconds4human(alarm.delay_down_duration, { negative_suffix: '' }) + '</code>, ';
1603                             }
1604                         }
1605                         if(alarm.delay_multiplier != 1.0) {
1606                             delay += 'multiplied&nbsp;by&nbsp;<code>' + alarm.delay_multiplier.toString() + '</code>';
1607                             delay += ',&nbsp;up&nbsp;to&nbsp;<code>' + seconds4human(alarm.delay_max_duration, { negative_suffix: '' }) + '</code>';
1608                         }
1609                         delay += '</small>';
1610                     }
1611
1612                     html += '<tr><td width="10%" style="text-align:right">check&nbsp;every</td><td>' + seconds4human(alarm.update_every, { negative_suffix: '' }) + '</td></tr>'
1613                         + ((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>'):'')
1614                         + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>'
1615                         + '</table></td></tr>';
1616
1617                     return html;
1618                 }
1619
1620                 function alarm_family_show(id) {
1621                     var html = '<table class="table">';
1622                     var family = options.alarm_families[id];
1623                     var len = family.arr.length;
1624                     while(len--) {
1625                         var alarm = family.arr[len];
1626                         html += alarm_to_html(alarm, true);
1627                     }
1628                     html += '</table>';
1629
1630                     $('#alarm_all_' + id.toString()).html(html);
1631                 }
1632
1633                 // find the proper family of each alarm
1634                 var now = Date.now();
1635                 var x;
1636                 var count_active = 0;
1637                 var count_all = 0;
1638                 var families = {};
1639                 var families_sort = new Array();
1640                 for(x in data.alarms) {
1641                     var alarm = data.alarms[x];
1642                     var family = alarm.family;
1643
1644                     // find the chart
1645                     var chart = options.data.charts[alarm.chart];
1646                     if(typeof chart === 'undefined')
1647                         chart = options.data.charts_by_name[alarm.chart];
1648
1649                     // not found - this should never happen!
1650                     if(typeof chart === 'undefined') {
1651                         console.log('WARNING: alarm ' + x + ' is linked to chart ' + alarm.chart + ', which is not found in the list of chart got from the server.');
1652                         chart = { priority: 9999999 };
1653                     }
1654                     else if(typeof chart.menu !== 'undefined' && typeof chart.submenu !== 'undefined')
1655                         // the family based on the chart
1656                         family = chart.menu + ' - ' + chart.submenu;
1657
1658                     if(typeof families[family] === 'undefined') {
1659                         families[family] = {
1660                             name: family,
1661                             arr: new Array(),
1662                             priority: chart.priority
1663                         };
1664
1665                         families_sort.push(families[family]);
1666                     }
1667
1668                     if(chart.priority < families[family].priority)
1669                         families[family].priority = chart.priority;
1670
1671                     families[family].arr.unshift(alarm);
1672                 }
1673
1674                 // sort the families, like the dashboard menu does
1675                 var families_sorted = families_sort.sort(function (a, b) {
1676                     if (a.priority > b.priority) return -1;
1677                     if (a.priority < b.priority) return 1;
1678                     return 0;
1679                 });
1680
1681                 var fc = 0;
1682                 var len = families_sorted.length;
1683                 while(len--) {
1684                     var family = families_sorted[len].name;
1685                     var active_family_added = false;
1686                     var expanded = 'true';
1687                     var collapsed = '';
1688                     var cin = 'in';
1689
1690                     if(fc !== 0) {
1691                         all += "</table></div></div></div>";
1692                         expanded = 'false';
1693                         collapsed = 'class="collapsed"'
1694                         cin = '';
1695                     }
1696
1697                     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() + '">';
1698
1699                     options.alarm_families[fc] = families[family];
1700
1701                     fc++;
1702
1703                     var arr = families[family].arr;
1704                     var c = arr.length;
1705                     while(c--) {
1706                         var alarm = arr[c];
1707                         if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') {
1708                             if(!active_family_added) {
1709                                 active_family_added = true;
1710                                 active += '<tr><th class="text-center" colspan="2"><h4>' + family + '</h4></th></tr>';
1711                             }
1712                             count_active++;
1713                             active += alarm_to_html(alarm, true);
1714                         }
1715
1716                         count_all++;
1717                     }
1718                 }
1719                 active += "</table>";
1720                 if(families_sorted.length > 0) all += "</div></div></div>";
1721                 all += "</div>";
1722
1723                 if(!count_active)
1724                     active += "<h4>Everything is normal. No raised alarms.</h4>";
1725                 else
1726                     active += footer;
1727
1728                 if(!count_all)
1729                     all += "<h4>No alarms are running in this system.</h4>";
1730                 else
1731                     all += footer;
1732
1733                 document.getElementById('alarms_active').innerHTML = active;
1734                 document.getElementById('alarms_all').innerHTML = all;
1735
1736                 if(families_sorted.length > 0) alarm_family_show(0);
1737
1738                 // register bootstrap events
1739                 $('#alarms_all_accordion').on('show.bs.collapse', function (d) {
1740                     var target = $(d.target);
1741                     var id = $(target).data('alarm-id');
1742                     alarm_family_show(id);
1743                 });
1744                 $('#alarms_all_accordion').on('hidden.bs.collapse', function (d) {
1745                     var target = $(d.target);
1746                     var id = $(target).data('alarm-id');
1747                     $('#alarm_all_' + id.toString()).html('');
1748                 });
1749
1750                 document.getElementById('alarms_log').innerHTML = '<h3>Alarm Log</h3><table id="alarms_log_table"></table>';
1751
1752                 loadBootstrapTable(function () {
1753                     $('#alarms_log_table').bootstrapTable({
1754                         url: NETDATA.alarms.server + '/api/v1/alarm_log?all',
1755                         cache: false,
1756                         pagination: true,
1757                         pageSize: 10,
1758                         showPaginationSwitch: false,
1759                         search: true,
1760                         searchTimeOut: 300,
1761                         searchAlign: 'left',
1762                         showColumns: true,
1763                         showExport: true,
1764                         exportDataType: 'basic',
1765                         exportOptions: {
1766                             fileName: 'netdata_alarm_log'
1767                         },
1768                         rowStyle: function(row, index) {
1769                             switch(row.status) {
1770                                 case 'CRITICAL' : return { classes: 'danger'  }; break;
1771                                 case 'WARNING'  : return { classes: 'warning' }; break;
1772                                 case 'UNDEFINED': return { classes: 'info'    }; break;
1773                                 case 'CLEAR'    : return { classes: 'success' }; break;
1774                             }
1775                             return {};
1776                         },
1777                         showFooter: false,
1778                         showHeader: true,
1779                         showRefresh: true,
1780                         showToggle: false,
1781                         sortable: true,
1782                         silentSort: false,
1783                         columns: [
1784                             {
1785                                 field: 'when',
1786                                 title: 'Event Date',
1787                                 valign: 'middle',
1788                                 titleTooltip: 'The date and time the even took place',
1789                                 formatter: function(value, row, index) { return timestamp4human(value, ' '); },
1790                                 align: 'center',
1791                                 valign: 'middle',
1792                                 switchable: false,
1793                                 sortable: true
1794                             },
1795                             {
1796                                 field: 'hostname',
1797                                 title: 'Host',
1798                                 valign: 'middle',
1799                                 titleTooltip: 'The host that generated this event',
1800                                 align: 'center',
1801                                 valign: 'middle',
1802                                 visible: false,
1803                                 sortable: true
1804                             },
1805                             {
1806                                 field: 'unique_id',
1807                                 title: 'Unique ID',
1808                                 titleTooltip: 'The host unique ID for 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_id',
1817                                 title: 'Alarm ID',
1818                                 titleTooltip: 'The ID of the alarm that generated this event',
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: 'alarm_event_id',
1827                                 title: 'Alarm Event ID',
1828                                 titleTooltip: 'The incremental ID of this event for the given alarm',
1829                                 formatter: function(value, row, index) { return alarmid4human(value); },
1830                                 align: 'center',
1831                                 valign: 'middle',
1832                                 visible: false,
1833                                 sortable: true
1834                             },
1835                             {
1836                                 field: 'chart',
1837                                 title: 'Chart',
1838                                 titleTooltip: 'The chart the alarm is attached to',
1839                                 align: 'center',
1840                                 valign: 'middle',
1841                                 switchable: false,
1842                                 sortable: true
1843                             },
1844                             {
1845                                 field: 'family',
1846                                 title: 'Family',
1847                                 titleTooltip: 'The family of the chart the alarm is attached to',
1848                                 align: 'center',
1849                                 valign: 'middle',
1850                                 visible: false,
1851                                 sortable: true
1852                             },
1853                             {
1854                                 field: 'name',
1855                                 title: 'Alarm',
1856                                 titleTooltip: 'The alarm name that generated this event',
1857                                 formatter: function(value, row, index) {
1858                                     return value.toString().replace(/_/g, ' ');
1859                                 },
1860                                 align: 'center',
1861                                 valign: 'middle',
1862                                 switchable: false,
1863                                 sortable: true
1864                             },
1865                             {
1866                                 field: 'value_string',
1867                                 title: 'Friendly Value',
1868                                 titleTooltip: 'The value of the alarm, that triggered this event',
1869                                 align: 'right',
1870                                 valign: 'middle',
1871                                 sortable: true
1872                             },
1873                             {
1874                                 field: 'old_value_string',
1875                                 title: 'Friendly Old Value',
1876                                 titleTooltip: 'The value of the alarm, just before this event',
1877                                 align: 'right',
1878                                 valign: 'middle',
1879                                 visible: false,
1880                                 sortable: true
1881                             },
1882                             {
1883                                 field: 'old_value',
1884                                 title: 'Old Value',
1885                                 titleTooltip: 'The value of the alarm, just before this event',
1886                                 formatter: function(value, row, index) {
1887                                     return ((value !== null)?Math.round(value * 100) / 100:'NaN').toString();
1888                                 },
1889                                 align: 'center',
1890                                 valign: 'middle',
1891                                 visible: false,
1892                                 sortable: true
1893                             },
1894                             {
1895                                 field: 'value',
1896                                 title: 'Value',
1897                                 titleTooltip: 'The value of the alarm, that triggered this event',
1898                                 formatter: function(value, row, index) {
1899                                     return ((value !== null)?Math.round(value * 100) / 100:'NaN').toString();
1900                                 },
1901                                 align: 'right',
1902                                 valign: 'middle',
1903                                 visible: false,
1904                                 sortable: true
1905                             },
1906                             {
1907                                 field: 'units',
1908                                 title: 'Units',
1909                                 titleTooltip: 'The units of the value of the alarm',
1910                                 align: 'left',
1911                                 valign: 'middle',
1912                                 visible: false,
1913                                 sortable: true
1914                             },
1915                             {
1916                                 field: 'old_status',
1917                                 title: 'Old Status',
1918                                 titleTooltip: 'The status of the alarm, just before this event',
1919                                 align: 'center',
1920                                 valign: 'middle',
1921                                 visible: false,
1922                                 sortable: true
1923                             },
1924                             {
1925                                 field: 'status',
1926                                 title: 'Status',
1927                                 titleTooltip: 'The status of the alarm, that was set due to this event',
1928                                 align: 'center',
1929                                 valign: 'middle',
1930                                 switchable: false,
1931                                 sortable: true
1932                             },
1933                             {
1934                                 field: 'duration',
1935                                 title: 'Last Duration',
1936                                 titleTooltip: 'The duration the alarm was at its previous state, just before this event',
1937                                 formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); },
1938                                 align: 'center',
1939                                 valign: 'middle',
1940                                 visible: false,
1941                                 sortable: true
1942                             },
1943                             {
1944                                 field: 'non_clear_duration',
1945                                 title: 'Raised Duration',
1946                                 titleTooltip: 'The duration the alarm was raised, just before this event',
1947                                 formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); },
1948                                 align: 'center',
1949                                 valign: 'middle',
1950                                 visible: false,
1951                                 sortable: true
1952                             },
1953                             {
1954                                 field: 'recipient',
1955                                 title: 'Recipient',
1956                                 titleTooltip: 'The recipient of this event',
1957                                 align: 'center',
1958                                 valign: 'middle',
1959                                 visible: false,
1960                                 sortable: true
1961                             },
1962                             {
1963                                 field: 'processed',
1964                                 title: 'Processed Status',
1965                                 titleTooltip: 'True when this event is processed',
1966                                 formatter: function(value, row, index) {
1967                                     if(value === true)
1968                                         return 'DONE';
1969                                     else
1970                                         return 'PENDING';
1971                                 },
1972                                 align: 'center',
1973                                 valign: 'middle',
1974                                 visible: false,
1975                                 sortable: true
1976                             },
1977                             {
1978                                 field: 'updated',
1979                                 title: 'Updated Status',
1980                                 titleTooltip: 'True when this event has been updated by another event',
1981                                 formatter: function(value, row, index) {
1982                                     if(value === true)
1983                                         return 'UPDATED';
1984                                     else
1985                                         return 'CURRENT';
1986                                 },
1987                                 align: 'center',
1988                                 valign: 'middle',
1989                                 visible: false,
1990                                 sortable: true
1991                             },
1992                             {
1993                                 field: 'updated_by_id',
1994                                 title: 'Updated By ID',
1995                                 titleTooltip: 'The unique ID of the event that obsoleted this one',
1996                                 formatter: function(value, row, index) { return alarmid4human(value); },
1997                                 align: 'center',
1998                                 valign: 'middle',
1999                                 visible: false,
2000                                 sortable: true
2001                             },
2002                             {
2003                                 field: 'updates_id',
2004                                 title: 'Updates ID',
2005                                 titleTooltip: 'The unique ID of the event obsoleted because of this event',
2006                                 formatter: function(value, row, index) { return alarmid4human(value); },
2007                                 align: 'center',
2008                                 valign: 'middle',
2009                                 visible: false,
2010                                 sortable: true
2011                             },
2012                             {
2013                                 field: 'exec',
2014                                 title: 'Script',
2015                                 titleTooltip: 'The script to handle the event notification',
2016                                 align: 'center',
2017                                 valign: 'middle',
2018                                 visible: false,
2019                                 sortable: true
2020                             },
2021                             {
2022                                 field: 'exec_run',
2023                                 title: 'Script Run At',
2024                                 titleTooltip: 'The date and time the script has been ran',
2025                                 formatter: function(value, row, index) { return timestamp4human(value, ' '); },
2026                                 align: 'center',
2027                                 valign: 'middle',
2028                                 visible: false,
2029                                 sortable: true
2030                             },
2031                             {
2032                                 field: 'exec_code',
2033                                 title: 'Script Return Value',
2034                                 titleTooltip: 'The return code of the script',
2035                                 formatter: function(value, row, index) {
2036                                     if(value === 0)
2037                                         return 'OK (returned 0)';
2038                                     else
2039                                         return 'FAILED (with code ' + value.toString() + ')';
2040                                 },
2041                                 align: 'center',
2042                                 valign: 'middle',
2043                                 visible: false,
2044                                 sortable: true
2045                             },
2046                             {
2047                                 field: 'delay',
2048                                 title: 'Script Delay',
2049                                 titleTooltip: 'The hysteresis of the notification',
2050                                 formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); },
2051                                 align: 'center',
2052                                 valign: 'middle',
2053                                 visible: false,
2054                                 sortable: true
2055                             },
2056                             {
2057                                 field: 'delay_up_to_timestamp',
2058                                 title: 'Script Delay Run At',
2059                                 titleTooltip: 'The date and time the script should be run, after hysteresis',
2060                                 formatter: function(value, row, index) { return timestamp4human(value, ' '); },
2061                                 align: 'center',
2062                                 valign: 'middle',
2063                                 visible: false,
2064                                 sortable: true
2065                             },
2066                             {
2067                                 field: 'info',
2068                                 title: 'Description',
2069                                 titleTooltip: 'A short description of the alarm',
2070                                 align: 'center',
2071                                 valign: 'middle',
2072                                 visible: false,
2073                                 sortable: true
2074                             },
2075                             {
2076                                 field: 'source',
2077                                 title: 'Alarm Source',
2078                                 titleTooltip: 'The source of configuration of the alarm',
2079                                 align: 'center',
2080                                 valign: 'middle',
2081                                 visible: false,
2082                                 sortable: true
2083                             }
2084                         ]
2085                     });
2086                     // console.log($('#alarms_log_table').bootstrapTable('getOptions'));
2087                 });
2088             });
2089         }
2090
2091         function alarmsCallback(data) {
2092             var count = 0;
2093             for(x in data.alarms) {
2094                 var alarm = data.alarms[x];
2095                 if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL')
2096                     count++;
2097             }
2098
2099             if(count > 0)
2100                 document.getElementById('alarms_count_badge').innerHTML = count.toString();
2101             else
2102                 document.getElementById('alarms_count_badge').innerHTML = '';
2103         }
2104
2105         function initializeDynamicDashboard(netdata_url) {
2106             if(typeof netdata_url === 'undefined' || netdata_url === null)
2107                 netdata_url = NETDATA.serverDefault;
2108
2109             // initialize clickable alarms
2110             NETDATA.alarms.chart_div_offset = 100;
2111             NETDATA.alarms.chart_div_id_prefix = 'chart_';
2112             NETDATA.alarms.chart_div_animation_duration = 0;
2113
2114             NETDATA.pause(function() {
2115                 NETDATA.alarms.callback = alarmsCallback;
2116
2117                 // download all the charts the server knows
2118                 NETDATA.chartRegistry.downloadAll(netdata_url, function(data) {
2119                     if(data !== null) {
2120                         options.hostname = data.hostname;
2121                         options.data = data;
2122
2123                         // update the dashboard hostname
2124                         document.getElementById('hostname').innerHTML = options.hostname;
2125                         document.getElementById('hostname').href = NETDATA.serverDefault;
2126
2127                         // update the dashboard title
2128                         document.title = options.hostname + ' netdata dashboard';
2129
2130                         // close the splash screen
2131                         $("#loadOverlay").css("display","none");
2132
2133                         // create a chart_by_name index
2134                         data.charts_by_name = {};
2135                         var charts = data.charts;
2136                         var x;
2137                         for(x in charts) {
2138                             var chart = charts[x];
2139                             data.charts_by_name[chart.name] = chart;
2140                         }
2141
2142                         // render all charts
2143                         renderChartsAndMenu(data);
2144                     }
2145                 });
2146             });
2147         }
2148
2149         // ----------------------------------------------------------------------------
2150
2151         function versionLog(msg) {
2152             document.getElementById('versionCheckLog').innerHTML = msg;
2153         }
2154
2155         function getNetdataVersion(callback) {
2156             versionLog('Downloading installed version info from netdata...');
2157
2158             $.ajax({
2159                 url: 'version.txt',
2160                 async: true,
2161                 cache: false,
2162                 xhrFields: { withCredentials: true } // required for the cookie
2163             })
2164             .done(function(data) {
2165                 data = data.replace(/(\r\n|\n|\r| |\t)/gm,"");
2166                 if(data.length !== 40) {
2167                     versionLog('Received version string is invalid.');
2168                     callback(null);
2169                 }
2170                 else {
2171                     versionLog('Installed version of netdata is ' + data);
2172                     document.getElementById('netdataVersion').innerHTML = data;
2173                     callback(data);
2174                 }
2175             })
2176             .fail(function() {
2177                 versionLog('Failed to download installed version info from netdata!');
2178                 callback(null);
2179             });
2180         }
2181
2182         function getGithubLatestCommit(callback) {
2183             versionLog('Downloading latest version info from github...');
2184
2185             $.ajax({
2186                 url: 'https://api.github.com/repos/firehol/netdata/commits',
2187                 async: true,
2188                 cache: false
2189             })
2190             .done(function(data) {
2191                 versionLog('Latest version info from github is ' + data[0].sha);
2192                 callback(data[0].sha);
2193             })
2194             .fail(function() {
2195                 versionLog('Failed to download installed version info from github!');
2196                 callback(null);
2197             });
2198         }
2199
2200         function checkForUpdate(callback) {
2201             getNetdataVersion(function(sha1) {
2202                 if(sha1 === null) callback(null, null);
2203
2204                 getGithubLatestCommit(function(sha2) {
2205                     callback(sha1, sha2);
2206                 });
2207             });
2208
2209             return null;
2210         }
2211
2212         function notifyForUpdate(force) {
2213             versionLog('<p>checking for updates...</p>');
2214
2215             var now = Date.now();
2216
2217             if(typeof force === 'undefined' || force !== true) {
2218                 var last = loadLocalStorage('last_update_check');
2219
2220                 if(typeof last === 'string')
2221                     last = parseInt(last);
2222                 else
2223                     last = 0;
2224
2225                 if(now - last < 3600000 * 8) {
2226                     // no need to check it - too soon
2227                     return;
2228                 }
2229             }
2230
2231             checkForUpdate(function(sha1, sha2) {
2232                 var save = false;
2233
2234                 if(sha1 === null) {
2235                     save = false;
2236                     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>');
2237                 }
2238                 else if(sha2 === null) {
2239                     save = false;
2240                     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>');
2241                 }
2242                 else if(sha1 === sha2) {
2243                     save = true;
2244                     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>');
2245                 }
2246                 else {
2247                     save = true;
2248                     var compare = 'https://github.com/firehol/netdata/compare/' + sha1.toString() + '...' + sha2.toString();
2249
2250                     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>');
2251
2252                     document.getElementById('update_badge').innerHTML = '!';
2253                 }
2254
2255                 if(save)
2256                     saveLocalStorage('last_update_check', now.toString());
2257             });
2258         }
2259
2260         // ----------------------------------------------------------------------------
2261
2262         function finalizePage() {
2263             // resize all charts - without starting the background thread
2264             // this has to be done while NETDATA is paused
2265             // if we ommit this, the affix menu will be wrong, since all
2266             // the Dom elements are initially zero-sized
2267             NETDATA.parseDom();
2268
2269             if(urlOptions.pan_and_zoom === true)
2270                 NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before);
2271
2272             // ------------------------------------------------------------------------
2273             // https://github.com/viralpatel/jquery.shorten/blob/master/src/jquery.shorten.js
2274             $.fn.shorten = function(settings) {
2275                 "use strict";
2276
2277                 var config = {
2278                     showChars: 750,
2279                     minHideChars: 10,
2280                     ellipsesText: "...",
2281                     moreText: '<i class="fa fa-expand" aria-hidden="true"></i> show more information',
2282                     lessText: '<i class="fa fa-compress" aria-hidden="true"></i> show less information',
2283                     onLess: function() { NETDATA.onscroll(); },
2284                     onMore: function() { NETDATA.onscroll(); },
2285                     errMsg: null,
2286                     force: false
2287                 };
2288
2289                 if (settings) {
2290                     $.extend(config, settings);
2291                 }
2292
2293                 if ($(this).data('jquery.shorten') && !config.force) {
2294                     return false;
2295                 }
2296                 $(this).data('jquery.shorten', true);
2297
2298                 $(document).off("click", '.morelink');
2299
2300                 $(document).on({
2301                     click: function() {
2302
2303                         var $this = $(this);
2304                         if ($this.hasClass('less')) {
2305                             $this.removeClass('less');
2306                             $this.html(config.moreText);
2307                             $this.parent().prev().animate({'height':'0'+'%'}, 0, function () { $this.parent().prev().prev().show(); }).hide(0, function() {
2308                                 config.onLess();
2309                             });
2310
2311                         } else {
2312                             $this.addClass('less');
2313                             $this.html(config.lessText);
2314                             $this.parent().prev().animate({'height':'100'+'%'}, 0, function () { $this.parent().prev().prev().hide(); }).show(0, function() {
2315                                 config.onMore();
2316                             });
2317                         }
2318                         return false;
2319                     }
2320                 }, '.morelink');
2321
2322                 return this.each(function() {
2323                     var $this = $(this);
2324
2325                     var content = $this.html();
2326                     var contentlen = $this.text().length;
2327                     if (contentlen > config.showChars + config.minHideChars) {
2328                         var c = content.substr(0, config.showChars);
2329                         if (c.indexOf('<') >= 0) // If there's HTML don't want to cut it
2330                         {
2331                             var inTag = false; // I'm in a tag?
2332                             var bag = ''; // Put the characters to be shown here
2333                             var countChars = 0; // Current bag size
2334                             var openTags = []; // Stack for opened tags, so I can close them later
2335                             var tagName = null;
2336
2337                             for (var i = 0, r = 0; r <= config.showChars; i++) {
2338                                 if (content[i] == '<' && !inTag) {
2339                                     inTag = true;
2340
2341                                     // This could be "tag" or "/tag"
2342                                     tagName = content.substring(i + 1, content.indexOf('>', i));
2343
2344                                     // If its a closing tag
2345                                     if (tagName[0] == '/') {
2346
2347
2348                                         if (tagName != '/' + openTags[0]) {
2349                                             config.errMsg = 'ERROR en HTML: the top of the stack should be the tag that closes';
2350                                         } else {
2351                                             openTags.shift(); // Pops the last tag from the open tag stack (the tag is closed in the retult HTML!)
2352                                         }
2353
2354                                     } else {
2355                                         // There are some nasty tags that don't have a close tag like <br/>
2356                                         if (tagName.toLowerCase() != 'br') {
2357                                             openTags.unshift(tagName); // Add to start the name of the tag that opens
2358                                         }
2359                                     }
2360                                 }
2361                                 if (inTag && content[i] == '>') {
2362                                     inTag = false;
2363                                 }
2364
2365                                 if (inTag) { bag += content.charAt(i); } // Add tag name chars to the result
2366                                 else {
2367                                     r++;
2368                                     if (countChars <= config.showChars) {
2369                                         bag += content.charAt(i); // Fix to ie 7 not allowing you to reference string characters using the []
2370                                         countChars++;
2371                                     } else // Now I have the characters needed
2372                                     {
2373                                         if (openTags.length > 0) // I have unclosed tags
2374                                         {
2375                                             //console.log('They were open tags');
2376                                             //console.log(openTags);
2377                                             for (j = 0; j < openTags.length; j++) {
2378                                                 //console.log('Cierro tag ' + openTags[j]);
2379                                                 bag += '</' + openTags[j] + '>'; // Close all tags that were opened
2380
2381                                                 // 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
2382                                             }
2383                                             break;
2384                                         }
2385                                     }
2386                                 }
2387                             }
2388                             c = $('<div/>').html(bag + '<span class="ellip">' + config.ellipsesText + '</span>').html();
2389                         }else{
2390                             c+=config.ellipsesText;
2391                         }
2392
2393                         var html = '<div class="shortcontent">' + c +
2394                                 '</div><div class="allcontent">' + content +
2395                                 '</div><span><a href="javascript://nop/" class="morelink">' + config.moreText + '</a></span>';
2396
2397                         $this.html(html);
2398                         $this.find(".allcontent").hide(); // Hide all text
2399                         $('.shortcontent p:last', $this).css('margin-bottom', 0); //Remove bottom margin on last paragraph as it's likely shortened
2400                     }
2401                 });
2402
2403             };
2404             $(".chart-message").shorten();
2405             // ------------------------------------------------------------------------
2406
2407             // callback for us to track PanAndZoom operations
2408             NETDATA.globalPanAndZoom.callback = urlOptions.netdataPanAndZoomCallback;
2409
2410             // let it run (update the charts)
2411             NETDATA.unpause();
2412
2413             // check if we have to jump to a specific section
2414             scrollToId(urlOptions.hash.replace('#',''));
2415
2416             if(urlOptions.chart !== null) {
2417                 NETDATA.alarms.scrollToChart(urlOptions.chart);
2418                 //urlOptions.hash = '#' + NETDATA.name2id('menu_' + charts[c].menu + '_submenu_' + charts[c].submenu);
2419                 //urlOptions.hash = '#chart_' + NETDATA.name2id(urlOptions.chart);
2420                 //console.log('hash = ' + urlOptions.hash);
2421             }
2422
2423             /* activate bootstrap sidebar (affix) */
2424             $('#sidebar').affix({
2425                 offset: {
2426                     top: (isdemo())?150:0,
2427                     bottom: 0
2428                 }
2429             });
2430
2431             /* fix scrolling of very long affix lists
2432                http://stackoverflow.com/questions/21691585/bootstrap-3-1-0-affix-too-long
2433              */
2434             $('#sidebar').on('affixed.bs.affix', function() {
2435                 $(this).removeAttr('style');
2436             });
2437
2438             /* activate bootstrap scrollspy (needed for sidebar) */
2439             $(document.body).scrollspy({
2440                 target: '#sidebar',
2441                 offset: $(window).height() / 5 // controls the diff of the <hX> element to the top, to select it
2442             });
2443
2444             // change the URL based on the current position of the screen
2445             $('#sidebar').on('activate.bs.scrollspy', function (e) {
2446                 // console.log(e);
2447                 var el = $(e.target);
2448                 //if(el.find('ul').size() == 0) {
2449                 var hash = el.find('a').attr('href');
2450                 if(typeof hash === 'string' && hash.substring(0, 1) === '#' && urlOptions.hash.startsWith(hash + '_submenu_') === false) {
2451                     urlOptions.hash = hash;
2452                     //console.log(urlOptions.hash);
2453                     urlOptions.hashUpdate();
2454                 }
2455                 //else console.log('hash: not accepting ' + hash);
2456                 //}
2457                 //else console.log('el.find(): not found');
2458             });
2459
2460             document.getElementById('footer').style.display = 'block';
2461
2462             var update_options_modal = function() {
2463                 // console.log('update_options_modal');
2464
2465                 var sync_option = function(option) {
2466                     var self = $('#' + option);
2467
2468                     if(self.prop('checked') !== NETDATA.getOption(option)) {
2469                         // console.log('switching ' + option.toString());
2470                         self.bootstrapToggle(NETDATA.getOption(option)?'on':'off');
2471                     }
2472                 }
2473
2474                 var theme_sync_option = function(option) {
2475                     var self = $('#' + option);
2476
2477                     self.bootstrapToggle(netdataTheme === 'slate'?'on':'off');
2478                 }
2479
2480                 sync_option('eliminate_zero_dimensions');
2481                 sync_option('destroy_on_hide');
2482                 sync_option('async_on_scroll');
2483                 sync_option('parallel_refresher');
2484                 sync_option('concurrent_refreshes');
2485                 sync_option('sync_selection');
2486                 sync_option('sync_pan_and_zoom');
2487                 sync_option('stop_updates_when_focus_is_lost');
2488                 sync_option('smooth_plot');
2489                 sync_option('pan_and_zoom_data_padding');
2490                 sync_option('show_help');
2491                 theme_sync_option('netdata_theme_control');
2492
2493                 if(NETDATA.getOption('parallel_refresher') === false) {
2494                     $('#concurrent_refreshes_row').hide();
2495                 }
2496                 else {
2497                     $('#concurrent_refreshes_row').show();
2498                 }
2499             };
2500             NETDATA.setOption('setOptionCallback', update_options_modal);
2501
2502             // handle options changes
2503             $('#eliminate_zero_dimensions').change(function()       { NETDATA.setOption('eliminate_zero_dimensions', $(this).prop('checked')); });
2504             $('#destroy_on_hide').change(function()                 { NETDATA.setOption('destroy_on_hide', $(this).prop('checked')); });
2505             $('#async_on_scroll').change(function()                 { NETDATA.setOption('async_on_scroll', $(this).prop('checked')); });
2506             $('#parallel_refresher').change(function()              { NETDATA.setOption('parallel_refresher', $(this).prop('checked')); });
2507             $('#concurrent_refreshes').change(function()            { NETDATA.setOption('concurrent_refreshes', $(this).prop('checked')); });
2508             $('#sync_selection').change(function()                  { NETDATA.setOption('sync_selection', $(this).prop('checked')); });
2509             $('#sync_pan_and_zoom').change(function()               { NETDATA.setOption('sync_pan_and_zoom', $(this).prop('checked')); });
2510             $('#stop_updates_when_focus_is_lost').change(function() {
2511                 urlOptions.update_always = !$(this).prop('checked');
2512                 urlOptions.hashUpdate();
2513
2514                 NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always);
2515             });
2516             $('#smooth_plot').change(function()                     { NETDATA.setOption('smooth_plot', $(this).prop('checked')); });
2517             $('#pan_and_zoom_data_padding').change(function()       { NETDATA.setOption('pan_and_zoom_data_padding', $(this).prop('checked')); });
2518             $('#show_help').change(function()                       {
2519                 urlOptions.help = $(this).prop('checked');
2520                 urlOptions.hashUpdate();
2521
2522                 NETDATA.setOption('show_help', urlOptions.help);
2523                 netdataReload();
2524             });
2525
2526             // this has to be the last
2527             // it reloads the page
2528             $('#netdata_theme_control').change(function() {
2529                 urlOptions.theme = $(this).prop('checked')?'slate':'white';
2530                 urlOptions.hashUpdate();
2531
2532                 if(setTheme(urlOptions.theme))
2533                     netdataReload();
2534             });
2535
2536             $('#updateModal').on('show.bs.modal', function() {
2537                 versionLog('checking, please wait...');
2538             });
2539
2540             $('#updateModal').on('shown.bs.modal', function() {
2541                 notifyForUpdate(true);
2542             });
2543
2544             $('#alarmsModal').on('shown.bs.modal', function() {
2545                 NETDATA.pause(alarmsUpdateModal);
2546             });
2547
2548             $('#alarmsModal').on('hidden.bs.modal', function() {
2549                 NETDATA.unpause();
2550                 document.getElementById('alarms_active').innerHTML =
2551                         document.getElementById('alarms_all').innerHTML =
2552                         document.getElementById('alarms_log').innerHTML =
2553                                 'loading...';
2554             });
2555
2556             $('#deleteRegistryModal').on('hidden.bs.modal', function() {
2557                 deleteRegistryGuid = null;
2558             });
2559
2560             if(isdemo()) {
2561                 // do not to give errors on netdata demo servers for 60 seconds
2562                 NETDATA.options.current.retries_on_data_failures = 60;
2563
2564                 if(urlOptions.nowelcome !== true) {
2565                     setTimeout(function() {
2566                         $('#welcomeModal').modal();
2567                     }, 1000);
2568                 }
2569
2570                 // google analytics when this is used for the home page of the demo sites
2571                 // this does not run on user's installations
2572                 setTimeout(function() {
2573                     (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
2574                     (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
2575                     m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
2576                     })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
2577
2578                     ga('create', 'UA-64295674-3', 'auto');
2579                     ga('send', 'pageview');
2580                 }, 2000);
2581             }
2582             else notifyForUpdate();
2583
2584             if(urlOptions.show_alarms === true)
2585                 setTimeout(function() { $('#alarmsModal').modal('show'); }, 1000);
2586
2587             var sidebar = document.getElementById('sidebar');
2588             Ps.initialize(sidebar, {
2589                 wheelSpeed: 0.5,
2590                 wheelPropagation: true,
2591                 swipePropagation: true,
2592                 minScrollbarLength: null,
2593                 maxScrollbarLength: null,
2594                 useBothWheelAxes: false,
2595                 suppressScrollX: true,
2596                 suppressScrollY: false,
2597                 scrollXMarginOffset: 0,
2598                 scrollYMarginOffset: 0,
2599                 theme: 'default'
2600             });
2601             Ps.update(sidebar);
2602
2603             var registry = document.getElementById('myNetdataDropdownUL');
2604             Ps.initialize(registry, {
2605                 wheelSpeed: 1,
2606                 wheelPropagation: false,
2607                 swipePropagation: false,
2608                 minScrollbarLength: null,
2609                 maxScrollbarLength: null,
2610                 useBothWheelAxes: false,
2611                 suppressScrollX: true,
2612                 suppressScrollY: false,
2613                 scrollXMarginOffset: 0,
2614                 scrollYMarginOffset: 0,
2615                 theme: 'default'
2616             });
2617             Ps.update(registry);
2618
2619             NETDATA.onresizeCallback = function() {
2620                 Ps.update(sidebar);
2621                 Ps.update(registry);
2622             };
2623
2624             $('#myNetdataDropdownParent')
2625                 .on('show.bs.dropdown', function () {
2626                     NETDATA.pause(function() {});
2627                 })
2628                 .on('shown.bs.dropdown', function () {
2629                     Ps.update(registry);
2630                 })
2631                 .on('hidden.bs.dropdown', function () {
2632                     NETDATA.unpause();
2633                 });
2634
2635             // var netdataEnded = performance.now();
2636             // console.log('start up time: ' + (netdataEnded - netdataStarted).toString() + ' ms');
2637         }
2638
2639         function resetDashboardOptions() {
2640             var help = NETDATA.options.current.show_help;
2641
2642             NETDATA.resetOptions();
2643             if(setTheme('slate'))
2644                 netdataReload();
2645
2646             if(help !== NETDATA.options.current.show_help)
2647                 netdataReload();
2648         }
2649
2650         // callback to add the dashboard info to the
2651         // parallel javascript downloader in netdata
2652         var netdataPrepCallback = function() {
2653             NETDATA.requiredCSS.push({
2654                 url: NETDATA.serverDefault + 'css/bootstrap-toggle-2.2.2.min.css',
2655                 isAlreadyLoaded: function() { return false; }
2656             });
2657
2658             NETDATA.requiredJs.push({
2659                 url: NETDATA.serverDefault + 'lib/bootstrap-toggle-2.2.2.min.js',
2660                 isAlreadyLoaded: function() { return false; }
2661             });
2662
2663             NETDATA.requiredJs.push({
2664                 url: NETDATA.serverDefault + 'dashboard_info.js?v20170115-1',
2665                 async: false,
2666                 isAlreadyLoaded: function() { return false; }
2667             });
2668
2669             if(isdemo()) {
2670                 document.getElementById('masthead').style.display = 'block';
2671             }
2672             else {
2673                 if(urlOptions.update_always === true)
2674                     NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always);
2675             }
2676         };
2677
2678         // our entry point
2679         // var netdataStarted = performance.now();
2680         var netdataCallback = initializeDynamicDashboard;
2681     </script>
2682 </head>
2683
2684 <body data-spy="scroll" data-target="#sidebar">
2685     <div id="loadOverlay" class="loadOverlay" style="background-color: #888; color: #888;">
2686         netdata<br/><div style="font-size: 3vh;">Real-time performance monitoring, done right!</div>
2687     </div>
2688     <script type="text/javascript">
2689         // change the loadOverlay colors ASAP to match the theme
2690         document.getElementById('loadOverlay').style = (urlOptions.theme === 'slate')?"background-color:#272b30; color: #373b40;":"background-color:#fff; color: #ddd;";
2691     </script>
2692     <nav class="navbar navbar-default navbar-fixed-top" role="banner">
2693         <div class="container">
2694             <nav id="mynetdata_nav" class="collapse navbar-collapse navbar-left hidden-sm hidden-xs" role="navigation" style="padding-right: 20px;">
2695                 <ul class="nav navbar-nav">
2696                     <li class="dropdown" id="myNetdataDropdownParent">
2697                         <a href="#" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a>
2698                         <ul class="dropdown-menu scrollable-menu inpagemenu multi-column columns-2" role="menu" id="myNetdataDropdownUL">
2699                             <div class="row">
2700                                 <div class="col-sm-6" style="width: 85%; padding-right: 0;">
2701                                     <ul id="mynetdata_servers" class="multi-column-dropdown">
2702                                         <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li>
2703                                     </ul>
2704                                 </div>
2705                                 <div class="col-sm-3 hidden-xs" style="width: 15%; padding-left: 0;">
2706                                     <ul id="mynetdata_actions1" class="multi-column-dropdown">
2707                                     <li style="color: #999;">&nbsp;</li>
2708                                     </ul>
2709                                 </div>
2710                             </div>
2711                         </ul>
2712                     </li>
2713                 </ul>
2714             </nav>
2715             <div class="navbar-header">
2716                 <button class="navbar-toggle" type="button" data-toggle="collapse" data-target=".navbar-collapse">
2717                     <span class="sr-only">Toggle navigation</span>
2718                     <span class="icon-bar"></span>
2719                     <span class="icon-bar"></span>
2720                     <span class="icon-bar"></span>
2721                 </button>
2722                 <a href="/" class="navbar-brand" id="hostname" title="reload the dashboard">netdata</a>
2723             </div>
2724             <nav class="collapse navbar-collapse navbar-right" role="navigation">
2725                 <ul class="nav navbar-nav">
2726                     <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>
2727                     <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>
2728                     <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>
2729                     <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>
2730                     <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>
2731                     <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>
2732                     <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>
2733                     <li class="dropdown hidden-sm hidden-md hidden-lg">
2734                         <a href="#" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a>
2735                         <ul id="mynetdata_servers2" class="dropdown-menu scrollable-menu inpagemenu" role="menu">
2736                             <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li>
2737                         </ul>
2738                     </li>
2739                 </ul>
2740             </nav>
2741         </div>
2742     </nav>
2743
2744     <div id="masthead" style="display: none;">
2745         <div class="container">
2746             <div class="row">
2747                 <div class="col-md-7">
2748                     <h1>Netdata
2749                         <p class="lead">Real-time performance monitoring, in the greatest possible detail</p>
2750                     </h1>
2751                 </div>
2752                 <div class="col-md-5">
2753                     <div class="well well-lg">
2754                         <div class="row">
2755                         <div class="col-md-6">
2756                             <b>Drag</b> charts to pan.
2757                             <b>Shift + wheel</b> on them, to zoom in and out.
2758                             <b>Double-click</b> on them, to reset.
2759                             <b>Hover</b> on them too!
2760                             </div>
2761                         <div class="col-md-6">
2762                             <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>
2763                             </div>
2764                         </div>
2765                     </div>
2766                 </div>
2767             </div>
2768         </div>
2769     </div>
2770
2771     <div class="container">
2772         <div class="row">
2773             <div class="charts-body" role="main">
2774                 <div id="charts_div"></div>
2775             </div>
2776             <div class="sidebar-body hidden-xs hidden-sm" id="sidebar-body" role="complementary">
2777                 <nav class="dashboard-sidebar hidden-print hidden-xs hidden-sm" id="sidebar" role="menu"></nav>
2778             </div>
2779         </div>
2780     </div>
2781
2782     <div id="footer" class="container" style="display: none;">
2783         <div class="row">
2784             <div class="col-md-10" role="main">
2785                 <div class="p">
2786                     <big><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></big><br/>
2787                     <i class="fa fa-copyright"></i> Copyright 2016-2017, <a href="mailto:costa@tsaousis.gr">Costa Tsaousis</a>.<br/>
2788                     Released under <a href="http://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">GPL v3 or later</a>.<br/>
2789                 </div>
2790                 <div class="p">
2791                     <small>
2792                         <a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a> re-distributes these software tools:
2793
2794                         <i class="fa fa-circle"></i> The excellent <a href="http://dygraphs.com/" target="_blank">Dygraphs.com</a> web chart library,
2795                         <i class="fa fa-copyright"></i> Copyright 2009, Dan Vanderkam, <a href="http://dygraphs.com/legal.html" target="_blank">MIT License</a>
2796
2797                         <i class="fa fa-circle"></i> <a href="https://rendro.github.io/easy-pie-chart/" target="_blank">Easy Pie Chart</a> web chart library,
2798                         <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>
2799
2800                         <i class="fa fa-circle"></i> <a href="http://bernii.github.io/gauge.js/" target="_blank">Gauge.js</a> web chart library,
2801                         <i class="fa fa-copyright"></i> Copyright, Bernard Kobos, <a href="http://bernii.github.io/gauge.js/" target="_blank">MIT License</a>
2802
2803                         <i class="fa fa-circle"></i> <a href="https://jquery.org/" target="_blank">jQuery</a>,
2804                         <i class="fa fa-copyright"></i> Copyright 2015, jQuery Foundation, <a href="https://jquery.org/license/" target="_blank">MIT License</a>
2805
2806                         <i class="fa fa-circle"></i> <a href="http://getbootstrap.com/getting-started/" target="_blank">Bootstrap</a>,
2807                         <i class="fa fa-copyright"></i> Copyright 2015, Twitter, <a href="http://getbootstrap.com/getting-started/#license-faqs" target="_blank">MIT License</a>
2808
2809                         <i class="fa fa-circle"></i> <a href="http://www.bootstraptoggle.com/" target="_blank">Bootstrap Toggle</a>,
2810                         <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>
2811
2812                         <i class="fa fa-circle"></i> <a href="https://github.com/noraesae/perfect-scrollbar" target="_blank">perfect-scrollbar</a>,
2813                         <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>
2814
2815                         <i class="fa fa-circle"></i> <a href="https://fortawesome.github.io/Font-Awesome/" target="_blank">FontAwesome</a>,
2816                         <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>
2817
2818                         <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.
2819
2820                         <i class="fa fa-circle"></i> <a href="http://bootstrap-table.wenzhixin.net.cn/" target="_blank">bootstrap-table</a>,
2821                         <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>
2822
2823                         <i class="fa fa-circle"></i> <a href="https://github.com/hhurz/tableExport.jquery.plugin" target="_blank">tableExport.jquery.plugin</a>,
2824                         <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>
2825
2826                     </small>
2827                 </div>
2828             </div>
2829         </div>
2830     </div>
2831
2832     <div class="modal fade" id="welcomeModal" tabindex="-1" role="dialog" aria-labelledby="welcomeModalLabel">
2833         <div class="modal-dialog modal-lg" role="document">
2834             <div class="modal-content">
2835                 <div class="modal-header">
2836                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2837                     <h4 class="modal-title" id="welcomeModalLabel">Welcome to the world of netdata</h4>
2838                 </div>
2839                 <div class="modal-body">
2840                     <div class="p">
2841                         <div style="width: 100%; text-align: center; padding-top: 10px; padding-bottom: 10px; font-size: 18px;">
2842                             if there is a metric for something, we want it visualised<br/>
2843                             and we want this visualisation to be <strong>real-time</strong>, <strong>efficient</strong> and <strong>awesome</strong>
2844                         </div>
2845                     </div>
2846                     <div class="p">
2847                         <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>
2848                         is a new way to monitor your systems and applications, to get <strong>real-time insights</strong>
2849                         of what is really happening and what affects performance.
2850                         It is carefully optimised to be a real-time system, without interfering in any way,
2851                         to the core function of your systems.
2852                     </div>
2853                     <div class="p">
2854                         <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>
2855                         has been designed to monitor <strong>massive amounts of metrics, per server, per second</strong>.
2856                         When installed, it might come up with 1k to 3k metrics, but we have been testing it with 100k
2857                         metrics, all collected per second, and still the cpu utilisation remained negligible.
2858                         <br/>
2859                         We have also tried to give each metric, a meaning, a context.
2860                         We have grouped and categorized all metrics into meaningful charts, providing a
2861                         better understanding of the underlying technologies and mechanisms.
2862                     </div>
2863                     <div class="p">
2864                         <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> is free,
2865                         open-source software. If you decide to use it,
2866                         <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>.
2867                     </div>
2868                     <div class="p">
2869                         Enjoy real-time performance monitoring!
2870                     </div>
2871                     <div class="p">
2872                         Costa Tsaousis
2873                     </div>
2874                 </div>
2875                 <div class="modal-footer">
2876                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2877                 </div>
2878             </div>
2879         </div>
2880     </div>
2881
2882     <div class="modal fade" id="helpModal" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel">
2883         <div class="modal-dialog modal-lg" role="document">
2884             <div class="modal-content">
2885                 <div class="modal-header">
2886                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2887                     <h4 class="modal-title" id="helpModalLabel">Dashboard Help</h4>
2888                 </div>
2889                 <div class="modal-body">
2890
2891                     <h4>Dygraphs (line, area and stacked area charts)</h4>
2892
2893                     <!-- Nav tabs -->
2894                     <ul class="nav nav-tabs" role="tablist">
2895                         <li role="presentation" class="active"><a href="#help_mouse" aria-controls="help_mouse" role="tab" data-toggle="tab">Mouse Interface</a></li>
2896                         <li role="presentation"><a href="#help_touch" aria-controls="help_touch" role="tab" data-toggle="tab">Touch Interface</a></li>
2897                     </ul>
2898
2899                     <!-- Tab panes -->
2900                     <div class="tab-content">
2901                         <div role="tabpanel" class="tab-pane active" id="help_mouse">
2902                             <div class="p">
2903                                 <h4>Mouse Over / Hover</h4>
2904                                 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).
2905                                 <br/>
2906                                 All the other visible charts will also show and highlight their values for the same timestamp.
2907                             </div>
2908                             <hr/>
2909                             <div class="p">
2910                                 <h4>Drag Chart Contents</h4>
2911                                 Drag the contents of a chart to pan it horizontally.
2912                                 <br/>
2913                                 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).
2914                                 <br/>
2915                                 Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double click</b> a panned chart.
2916                             </div>
2917                             <hr/>
2918                             <div class="p">
2919                                 <h4>Double Click</h4>
2920                                 Double Click a chart to reset all the charts to their default auto-refreshing state.
2921                             </div>
2922                             <hr/>
2923                             <div class="p">
2924                                 <h4>SHIFT + Drag</h4>
2925                                 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:
2926                                 <ul>
2927                                     <li>The already loaded chart contents are zoomed (low resolution)</li>
2928                                     <li>New data are transferred from the netdata server, to refresh the chart with possibly more detail.</li>
2929                                 </ul>
2930                                 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
2931                             </div>
2932                             <hr/>
2933                             <div class="p">
2934                                 <h4>SHIFT + Mouse Wheel</h4>
2935                                 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.
2936                                 <br/>
2937                                 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
2938                             </div>
2939                             <hr/>
2940                             <div class="p">
2941                                 <h4>Legend Operations</h4>
2942                                 Click on the label or value of a dimension, will select / un-select this dimension.
2943                                 <br/>
2944                                 You can press any of the SHIFT or CONTROL keys and then click on legend labels or values, to select / un-select multiple dimensions.
2945                             </div>
2946                         </div>
2947                         <div role="tabpanel" class="tab-pane" id="help_touch">
2948                             <div class="p">
2949                                 <h4>Single Tap</h4>
2950                                 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).
2951                                 <br/>
2952                                 All the other visible charts will also show and highlight their values for the same timestamp.
2953                             </div>
2954                             <hr/>
2955                             <div class="p">
2956                                 <h4>Drag Chart Contents</h4>
2957                                 Touch and Drag the contents of a chart to pan it horizontally.
2958                                 <br/>
2959                                 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).
2960                                 <br/>
2961                                 Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double tap</b> a panned chart.
2962                             </div>
2963                             <hr/>
2964                             <div class="p">
2965                                 <h4>Double Tap</h4>
2966                                 Double tap a chart to reset all the charts to their default auto-refreshing state.
2967                             </div>
2968                             <hr/>
2969                             <div class="p">
2970                                 <h4>Zoom <small>(does not work on firefox and IE/Edge)</small></h4>
2971                                 With two fingers, zoom in or out.
2972                                 <br/>
2973                                 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
2974                             </div>
2975                             <hr/>
2976                             <div class="p">
2977                                 <h4>Legend Operations</h4>
2978                                 Tap on the label or value of a dimension, will select / un-select this dimension.
2979                             </div>
2980                         </div>
2981                     </div>
2982                 </div>
2983                 <div class="modal-footer">
2984                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2985                 </div>
2986             </div>
2987         </div>
2988     </div>
2989
2990     <div class="modal fade" id="alarmsModal" tabindex="-1" role="dialog" aria-labelledby="alarmsModalLabel">
2991         <div class="modal-dialog modal-lg" role="document"  style="display: table;"> <!-- allow the modal to expand horizontally -->
2992             <div class="modal-content">
2993                 <div class="modal-header">
2994                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2995                     <h4 class="modal-title" id="alarmsModalLabel">netdata alarms</h4>
2996                 </div>
2997                 <div class="modal-body">
2998                     <!-- Nav tabs -->
2999                     <ul class="nav nav-tabs" role="tablist">
3000                         <li role="presentation" class="active"><a href="#alarms_active" aria-controls="alarms_active" role="tab" data-toggle="tab">Active</a></li>
3001                         <li role="presentation"><a href="#alarms_all" aria-controls="alarms_all" role="tab" data-toggle="tab">All</a></li>
3002                         <li role="presentation"><a href="#alarms_log" aria-controls="alarms_log" role="tab" data-toggle="tab">Log</a></li>
3003                     </ul>
3004
3005                     <!-- Tab panes -->
3006                     <div class="tab-content">
3007                         <div role="tabpanel" class="tab-pane active" id="alarms_active">
3008                             loading...
3009                         </div>
3010                         <div role="tabpanel" class="tab-pane" id="alarms_all">
3011                             loading...
3012                         </div>
3013                         <div role="tabpanel" class="tab-pane" id="alarms_log">
3014                             loading...
3015                         </div>
3016                     </div>
3017                 </div>
3018                 <div class="modal-footer">
3019                     <!-- <a href="#" onclick="alarmsUpdateModal(); return false;" type="button" class="btn btn-default">Update</a> -->
3020                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3021                 </div>
3022             </div>
3023         </div>
3024     </div>
3025
3026     <div class="modal fade" id="optionsModal" tabindex="-1" role="dialog" aria-labelledby="optionsModalLabel">
3027         <div class="modal-dialog modal-lg" role="document">
3028             <div class="modal-content">
3029                 <div class="modal-header">
3030                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
3031                     <h4 class="modal-title" id="optionsModalLabel">netdata dashboard options</h4>
3032                 </div>
3033                 <div class="modal-body">
3034                     <center>
3035                         <small style="color: #BBBBBB;">These are browser settings. Each viewer has its own. They do not affect the operation of your netdata server.
3036                         <br/>
3037                         Settings take effect immediately and are saved permanently to browser local storage (except the refresh on focus / always option).
3038                         <br/>
3039                         To reset all options (including charts sizes) to their defaults, click <a href="#" onclick="resetDashboardOptions(); return false;">here</a>.</small>
3040                     </center>
3041                     <div style="padding: 10px;"></div>
3042
3043                     <!-- Nav tabs -->
3044                     <ul class="nav nav-tabs" role="tablist">
3045                         <li role="presentation" class="active"><a href="#settings_performance" aria-controls="settings_performance" role="tab" data-toggle="tab">Performance</a></li>
3046                         <li role="presentation"><a href="#settings_sync" aria-controls="settings_sync" role="tab" data-toggle="tab">Synchronization</a></li>
3047                         <li role="presentation"><a href="#settings_visual" aria-controls="settings_visual" role="tab" data-toggle="tab">Visual</a></li>
3048                     </ul>
3049
3050                     <!-- Tab panes -->
3051                     <div class="tab-content">
3052                         <div role="tabpanel" class="tab-pane active" id="settings_performance">
3053                             <form id="optionsForm1" method="get" class="form-horizontal">
3054                                 <div class="form-group">
3055                                     <table>
3056                                     <tr class="option-row">
3057                                         <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>
3058                                         <td class="option-info"><strong>When to refresh the charts?</strong><br/>
3059                                             <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>
3060                                         </td>
3061                                         </tr>
3062                                     <tr class="option-row">
3063                                         <td class="option-control">
3064                                         <input id="eliminate_zero_dimensions" type="checkbox" checked data-toggle="toggle" data-on="Non Zero" data-off="All" data-width="110px">
3065                                         </td>
3066                                         <td class="option-info"><strong>Which dimensions to show?</strong><br/>
3067                                             <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>
3068                                         </td>
3069                                         </tr>
3070                                     <tr class="option-row">
3071                                         <td class="option-control"><input id="destroy_on_hide" type="checkbox" data-toggle="toggle" data-on="Destroy" data-off="Hide" data-width="110px"></td>
3072                                         <td class="option-info"><strong>How to handle hidden charts?</strong><br/>
3073                                             <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>
3074                                         </td>
3075                                         </tr>
3076                                     <tr class="option-row">
3077                                         <td class="option-control"><input id="async_on_scroll" type="checkbox" data-toggle="toggle" data-on="Async" data-off="Sync" data-width="110px"></td>
3078                                         <td class="option-info"><strong>Page scroll handling?</strong><br/>
3079                                             <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>
3080                                         </td>
3081                                         </tr>
3082                                     </table>
3083                                 </div>
3084                             </form>
3085                         </div>
3086                         <div role="tabpanel" class="tab-pane" id="settings_sync">
3087                             <form id="optionsForm2" method="get" class="form-horizontal">
3088                                 <div class="form-group">
3089                                     <table>
3090                                     <tr class="option-row">
3091                                         <td class="option-control"><input id="parallel_refresher" type="checkbox" checked data-toggle="toggle" data-on="Parallel" data-off="Sequential" data-width="110px"></td>
3092                                         <td class="option-info"><strong>Which chart refresh policy to use?</strong><br/>
3093                                             <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>
3094                                         </td>
3095                                     </tr>
3096                                     <tr class="option-row" id="concurrent_refreshes_row">
3097                                         <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>
3098                                         <td class="option-info"><strong>Shall we re-sync chart refreshes?</strong><br/>
3099                                             <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>
3100                                         </td>
3101                                     </tr>
3102                                     <tr class="option-row">
3103                                         <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>
3104                                         <td class="option-info"><strong>Sync hover selection on all charts?</strong><br/>
3105                                             <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>
3106                                         </td>
3107                                         </tr>
3108                                     <tr class="option-row">
3109                                         <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>
3110                                         <td class="option-info"><strong>Sync pan and zoom on all charts?</strong><br/>
3111                                             <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>
3112                                         </td>
3113                                         </tr>
3114                                     </table>
3115                                 </div>
3116                             </form>
3117                         </div>
3118                         <div role="tabpanel" class="tab-pane" id="settings_visual">
3119                             <form id="optionsForm3" method="get" class="form-horizontal">
3120                                 <div class="form-group">
3121                                     <table>
3122                                     <tr class="option-row">
3123                                         <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>
3124                                         <td class="option-info"><strong>Which theme to use?</strong><br/>
3125                                             <small>Netdata comes with two themes: <b>Dark</b> (the default) and <b>White</b>.
3126                                             <br/>
3127                                             <b>Switching this will reload the dashboard</b>.
3128                                             </small>
3129                                         </td>
3130                                         </tr>
3131                                     <tr class="option-row">
3132                                         <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>
3133                                         <td class="option-info"><strong>Do you need help?</strong><br/>
3134                                             <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.
3135                                             <br/>
3136                                             <b>Switching this will reload the dashboard</b>.
3137                                             </small>
3138                                         </td>
3139                                         </tr>
3140                                     <tr class="option-row">
3141                                         <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>
3142                                         <td class="option-info"><strong>Enable data padding when panning and zooming?</strong><br/>
3143                                             <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>
3144                                         </td>
3145                                         </tr>
3146                                     <tr class="option-row">
3147                                         <td class="option-control"><input id="smooth_plot" type="checkbox" checked data-toggle="toggle"  data-on="Smooth" data-off="Rough" data-width="110px"></td>
3148                                         <td class="option-info"><strong>Enable Bézier lines on charts?</strong><br/>
3149                                             <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.
3150                                             <br/>
3151                                             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>
3152                                         </td>
3153                                         </tr>
3154                                     </table>
3155                                 </div>
3156                             </form>
3157                         </div>
3158                     </div>
3159                 </div>
3160                 <div class="modal-footer">
3161                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3162                 </div>
3163             </div>
3164         </div>
3165     </div>
3166
3167
3168     <div class="modal fade" id="updateModal" tabindex="-1" role="dialog" aria-labelledby="updateModalLabel">
3169         <div class="modal-dialog" role="document">
3170             <div class="modal-content">
3171                 <div class="modal-header">
3172                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
3173                     <h4 class="modal-title" id="updateModalLabel">Update Check</h4>
3174                 </div>
3175                 <div class="modal-body">
3176                     Your netdata version: <b><code><span id="netdataVersion">Unknown</span></code></b>
3177                     <br/>
3178                     <div style="padding: 10px;"></div>
3179                     <div id="versionCheckLog">Not checked yet. Please press the Check Now button.</div>
3180                     <div>
3181                         <hr/>
3182                     </div>
3183                     <div>
3184                         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>.
3185                         <br/>
3186                         <small>
3187                             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>,
3188                             or <a href="https://github.com/firehol/netdata" target="_blank">watch netdata on <i class="fa fa-github" aria-hidden="true"></i> github</a>.
3189                         </small>
3190                     </div>
3191                 </div>
3192                 <div class="modal-footer">
3193                     <a href="#" onclick="notifyForUpdate(true); return false;" type="button" class="btn btn-default">Check Now</a>
3194                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3195                 </div>
3196             </div>
3197         </div>
3198     </div>
3199
3200     <div class="modal fade" id="deleteRegistryModal" tabindex="-1" role="dialog" aria-labelledby="deleteRegistryModalLabel">
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="deleteRegistryModalLabel">Delete <span id="deleteRegistryServerName"></span>?</h4>
3206                 </div>
3207                 <div class="modal-body">
3208                     You are about to delete, from your personal list of netdata servers, the following server:
3209                     <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;">
3210                     <b><span id="deleteRegistryServerName2"></span></b>
3211                     <br/>
3212                     <b><span id="deleteRegistryServerURL"></span></b>
3213                     </p>
3214                     Are you sure you want to do this?
3215                     <br/>
3216                     <div style="padding: 10px;"></div>
3217                     <small>Keep in mind, this server will be added back if and when you visit it again.</small>
3218                     <br/>
3219                     <div id="deleteRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
3220                 </div>
3221                 <div class="modal-footer">
3222                     <button type="button" class="btn btn-success" data-dismiss="modal">keep it</button>
3223                     <a href="#" onclick="notifyForDeleteRegistry(true); return false;" type="button" class="btn btn-danger">delete it</a>
3224                 </div>
3225             </div>
3226         </div>
3227     </div>
3228
3229     <div class="modal fade" id="switchRegistryModal" tabindex="-1" role="dialog" aria-labelledby="switchRegistryModalLabel">
3230         <div class="modal-dialog" role="document">
3231             <div class="modal-content">
3232                 <div class="modal-header">
3233                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
3234                     <h4 class="modal-title" id="switchRegistryModalLabel">Switch Netdata Registry Identity</h4>
3235                 </div>
3236                 <div class="modal-body">
3237                     You can copy and paste the following ID to all your browsers (e.g. work and home).
3238                     <br/>
3239                     All the browsers with the same ID will identify <b>you</b>, so please don't share this with others.
3240                     <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;">
3241                         <form action="#">
3242                             <input type="text" class="form-control" id="switchRegistryPersonGUID" placeholder="your personal ID" maxlength="36" autocomplete="off" style="text-align: center; font-size: 1.4em;">
3243                         </form>
3244                     </p>
3245                     Either copy this ID and paste it to another browser, or paste here the ID you have taken from another browser.
3246                     <p style="padding-top: 10px;"><small>
3247                         Keep in mind that:
3248                         <ul>
3249                             <li>when you switch ID, your previous ID will be lost forever - this is irreversible.</li>
3250                             <li>both IDs (your old and the new) must list this netdata at their personal lists.</li>
3251                             <li>both IDs have to be known by the registry: <b><span id="switchRegistryURL"></span></b>.</li>
3252                             <li>to get a new ID, just clear your browser cookies.</li>
3253                         </ul>
3254                     </small></p>
3255                     <div id="switchRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
3256                 </div>
3257                 <div class="modal-footer">
3258                     <button type="button" class="btn btn-success" data-dismiss="modal">cancel</button>
3259                     <a href="#" onclick="notifyForSwitchRegistry(true); return false;" type="button" class="btn btn-danger">impersonate</a>
3260                 </div>
3261             </div>
3262         </div>
3263     </div>
3264
3265     <div class="modal fade" id="gotoServerModal" tabindex="-1" role="dialog" aria-labelledby="gotoServerModalLabel">
3266         <div class="modal-dialog" role="document">
3267             <div class="modal-content">
3268                 <div class="modal-header">
3269                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
3270                     <h4 class="modal-title" id="gotoServerModalLabel"><span id="gotoServerName"></span></h4>
3271                 </div>
3272                 <div class="modal-body">
3273                     Checking known URLs for this server...
3274                     <div  style="padding-top: 20px;">
3275                         <table id="gotoServerList">
3276                         </table>
3277                     </div>
3278                     <p style="padding-top: 10px;"><small>
3279                         Checks may fail if you are viewing an HTTPS page and the server to be checked is HTTP only.
3280                     </small></p>
3281                     <div id="gotoServerResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
3282                 </div>
3283                 <div class="modal-footer">
3284                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3285                 </div>
3286             </div>
3287         </div>
3288     </div>
3289 </body>
3290 </html>
3291 <script type="text/javascript" src="dashboard.js?v20170127-1"></script>