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