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