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