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