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