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