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