4 <title>netdata dashboard</title>
5 <meta name="application-name" content="netdata">
7 <meta http-equiv="Content-Type" content="text/html; 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">
15 <!-- <link rel="shortcut icon" href="images/seo-performance-multi-size.ico"> -->
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"> -->
21 <!-- <link rel="icon" type="image/png" sizes="512x512" href="images/seo-performance-512.png"> -->
22 <!-- <link rel="icon" type="image/png" sizes="256x256" href="images/seo-performance-256.png"> -->
23 <!-- <link rel="icon" type="image/png" sizes="128x128" href="images/seo-performance-128.png"> -->
24 <!-- <link rel="icon" type="image/png" sizes="64x64" href="images/seo-performance-64.png"> -->
25 <!-- <link rel="icon" type="image/png" sizes="48x48" href="images/seo-performance-48.png"> -->
26 <!-- <link rel="icon" type="image/png" sizes="24x24" href="images/seo-performance-24.png"> -->
27 <!-- <link rel="icon" type="image/png" sizes="16x16" href="images/seo-performance-16.png"> -->
28 <!-- <link rel="icon" type="image/png" sizes="32x32" href="images/seo-performance-32.png"> -->
30 <link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACNklEQVRYhcXXv2tUQRAH8M+FEIJISBHCIWIhIQSUILERi4AiiqCggiIiomAjlhaC4j+ghYWISgqNohZaCBZBC8Ei8QdEUCutFBsxCBqDYkgci/cunkfuJffjJQPD8mZm5/vd2WV2HzlJ0Bs8CvrywsgCHwy+BpGOg0sJfjj4nYKX9FdwKG9gwZlgtgK8pLOpPxfw1mCoCnClDgWtzQTvCEYWCV7SkWAlFBoEb8dlDKBF8t2bMWUSH/AHr3CiEfz5CPUusPJLkRCdk5ZqyeqUrQv4R7E5TwK7M3zTeIKduRAIitiWEfIY69GdCwGcRFuG/xqONRkzkaA7+J5x+MaDtWmHvJ4HgeEM8Nn0bridfv9HoOFyBAdwJCPkqqTzHWwUaz7wgeBHxupfBKuCj2W25mxBsCGYyAB/FxTT27HcPlyep64tCLbjKbqqhLzBlgKfF8pVE4FgRXABI+ioEnYfOyzcFWsCbg+OV+xlpU4ER4O+4HVwL51b3xYEXcGu4Ao+YQhr5gmdxHmsQyfG0b/YxbWmLfRWmnxa0s06VbTMCpnBS9zFzQKTwR5cXCzwHIE02Sl8wSZsRI/kgLVJqjSd+t9LVjiG1diPszhdK3A5gR48k5zYMTwscC59sfT799CYKvA8EttbSeXgTr3gJQKl91kR+yTlvyG5uUbLYh9gb+ovltkb6qYtNSRo3kOygsBSzGlKsubf43USWLYK5CLLXoFWyU/CtzLbVDpW2n+m40yN9ukqdvAX9ac/EIgOapcAAAAASUVORK5CYII=">
32 <meta property="og:locale" content="en_US" />
33 <meta property="og:url" content="https://my-netdata.io" />
34 <meta property="og:type" content="website" />
35 <meta property="og:site_name" content="netdata"/>
36 <meta property="og:title" content="Get control of your Linux Servers. Simple. Effective. Awesome." />
37 <meta property="og:description" content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms." />
38 <meta property="og:image" content="https://cloud.githubusercontent.com/assets/2662304/22945737/e98cd0c6-f2fd-11e6-96f1-5501934b0955.png" />
39 <meta property="og:image:type" content="image/png" />
40 <meta property="fb:app_id" content="1200089276712916" />
42 <meta name="twitter:card" content="summary" />
43 <meta name="twitter:site" content="@linuxnetdata" />
44 <meta name="twitter:title" content="Get control of your Linux Servers. Simple. Effective. Awesome." />
45 <meta name="twitter:description" content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms." />
46 <meta name="twitter:image" content="https://cloud.githubusercontent.com/assets/2662304/14092712/93b039ea-f551-11e5-822c-beadbf2b2a2e.gif" />
49 /* prevent body from hiding under the navbar */
62 font-family: sans-serif;
63 padding: 40vh 0 40vh 0;
68 .modal-wide .modal-dialog {
72 /* fix # anchors scrolling under the navbar
73 https://github.com/twbs/bootstrap/issues/1768#issuecomment-46519033
83 h1:before, h2:before {
123 /* fix the navbar shifting when a modal is open */
124 /* https://github.com/twbs/bootstrap/issues/14040#issuecomment-159891033 */
126 width: 100% !important;
127 padding-right: 0 !important;
128 /* overflow-y: scroll !important; */
129 /* position: fixed !important;*/
133 /* make accordion use the whole header bar for expand/collapse */
143 * Scrollspy and affixed enhanced navigation to highlight sections and secondary
144 * sections of docs content.
149 top: 70px !important;
158 max-height: calc(100% - 70px) !important;
160 /*width: 220px !important;*/
163 /* By default it's not affixed in mobile views, so undo that */
164 .dashboard-sidebar.affix {
168 @media (min-width: 768px) {
174 /* First level of nav */
180 /* All levels of nav */
181 .dashboard-sidebar .nav > li > a {
188 .dashboard-sidebar .nav > li > a > .fa {
192 .dashboard-sidebar .nav > li > a:hover,
193 .dashboard-sidebar .nav > li > a:focus {
196 text-decoration: none;
197 background-color: transparent;
198 border-left: 1px solid #563d7c;
200 .dashboard-sidebar .nav > .active > a,
201 .dashboard-sidebar .nav > .active:hover > a,
202 .dashboard-sidebar .nav > .active:focus > a {
206 background-color: transparent;
207 border-left: 2px solid #563d7c;
210 /* Nav: second level (shown on .active) */
211 .dashboard-sidebar .nav .nav {
212 display: none; /* Hide by default, but at >768px, show it */
213 padding-bottom: 10px;
215 .dashboard-sidebar .nav .nav > li > a {
222 .dashboard-sidebar .nav .nav > li > a:hover,
223 .dashboard-sidebar .nav .nav > li > a:focus {
226 .dashboard-sidebar .nav .nav > .active > a,
227 .dashboard-sidebar .nav .nav > .active:hover > a,
228 .dashboard-sidebar .nav .nav > .active:focus > a {
236 .dropdown-menu.columns-2 {
241 .dropdown-menu li a {
245 .dropdown-menu.multi-column {
248 .multi-column-dropdown {
252 .multi-column-dropdown li a {
255 line-height: 1.428571429;
258 .multi-column-dropdown li a:hover {
259 text-decoration: none;
261 background-color: #262626;
269 /* Back to top (hidden on mobile) */
271 .dashboard-theme-toggle {
281 .dashboard-theme-toggle:hover {
283 text-decoration: none;
285 .dashboard-theme-toggle {
290 width: calc(100% - 20px) !important;
294 display: inline-block;
303 @media (min-width: 768px) {
310 .dashboard-theme-toggle {
315 /* Show and affix the side nav when space allows it */
316 @media (min-width: 992px) {
318 padding-left: 0% !important;
322 width: calc(100% - 213px) !important;
323 padding-left: 1% !important;
324 padding-right: 0% !important;
328 display: inline-block !important;
329 width: 213px !important;
332 .dashboard-sidebar .nav > .active > ul {
336 /* Widen the fixed sidebar */
337 .dashboard-sidebar.affix,
338 .dashboard-sidebar.affix-top,
339 .dashboard-sidebar.affix-bottom {
340 width: 213px !important;
342 .dashboard-sidebar.affix {
343 position: fixed; /* Undo the static from mobile first approach */
346 .dashboard-sidebar.affix-bottom {
347 position: absolute; /* Undo the static from mobile first approach */
349 .dashboard-sidebar.affix-bottom .dashboard-sidenav,
350 .dashboard-sidebar.affix .dashboard-sidenav {
356 @media (min-width: 1200px) {
358 padding-left: 2% !important;
362 width: calc(100% - 233px) !important;
363 padding-left: 1% !important;
364 padding-right: 1% !important;
368 display: inline-block !important;
369 width: 233px !important;
372 /* Widen the fixed sidebar again */
373 .dashboard-sidebar.affix,
374 .dashboard-sidebar.affix-top,
375 .dashboard-sidebar.affix-bottom {
376 width: 233px !important;
380 @media (min-width: 1360px) {
382 padding-left: 3% !important;
386 width: calc(100% - 263px) !important;
387 padding-left: 1% !important;
388 padding-right: 2% !important;
392 display: inline-block !important;
393 width: 263px !important;
396 /* Widen the fixed sidebar again */
397 .dashboard-sidebar.affix,
398 .dashboard-sidebar.affix-top,
399 .dashboard-sidebar.affix-bottom {
400 width: 263px !important;
406 <!-- check which theme to use -->
407 <script type="text/javascript">
408 // enable alarms checking and notifications
409 var netdataShowAlarms = true;
411 // enable registry updates
412 var netdataRegistry = true;
414 // --------------------------------------------------------------------
421 update_always: false,
434 hasProperty: function(property) {
435 // console.log('checking property ' + property + ' of type ' + typeof(this[property]));
436 return typeof this[property] !== 'undefined';
439 genHash: function() {
440 var hash = urlOptions.hash;
442 if(urlOptions.pan_and_zoom === true) {
443 hash += ';after=' + urlOptions.after.toString() +
444 ';before=' + urlOptions.before.toString();
447 if(urlOptions.theme !== null)
448 hash += ';theme=' + urlOptions.theme.toString();
450 if(urlOptions.help !== null)
451 hash += ';help=' + urlOptions.help.toString();
453 if(urlOptions.update_always === true)
454 hash += ';update_always=true';
459 parseHash: function() {
460 var variables = document.location.hash.split(';');
461 var len = variables.length;
464 var p = variables[len].split('=');
465 if(urlOptions.hasProperty(p[0]) && typeof p[1] !== 'undefined')
466 urlOptions[p[0]] = decodeURIComponent(p[1]);
469 if(variables[len].length > 0)
470 urlOptions.hash = variables[len];
474 var booleans = [ 'nowelcome', 'show_alarms', 'pan_and_zoom', 'update_always' ];
475 len = booleans.length;
477 if(urlOptions[booleans[len]] === 'true' || urlOptions[booleans[len]] === true || urlOptions[booleans[len]] === '1' || urlOptions[booleans[len]] === 1)
478 urlOptions[booleans[len]] = true;
480 urlOptions[booleans[len]] = false;
483 if(urlOptions.before > 0 && urlOptions.after > 0) {
484 urlOptions.pan_and_zoom = true;
485 urlOptions.nowelcome = true;
488 urlOptions.pan_and_zoom = false;
490 // console.log(urlOptions);
493 hashUpdate: function() {
494 history.replaceState(null, '', urlOptions.genHash());
497 netdataPanAndZoomCallback: function(status, after, before) {
498 urlOptions.pan_and_zoom = status;
499 urlOptions.after = after;
500 urlOptions.before = before;
501 urlOptions.hashUpdate();
506 urlOptions.parseHash();
508 // --------------------------------------------------------------------
509 // check options that should be processed before loading netdata.js
511 var localStorageTested = -1;
512 function localStorageTest() {
513 if(localStorageTested !== -1)
514 return localStorageTested;
516 if(typeof Storage !== "undefined" && typeof localStorage === 'object') {
519 localStorage.setItem(test, test);
520 localStorage.removeItem(test);
521 localStorageTested = true;
524 localStorageTested = false;
528 localStorageTested = false;
530 return localStorageTested;
533 function loadLocalStorage(name) {
537 if(localStorageTest() === true)
538 ret = localStorage.getItem(name);
542 if(typeof ret === 'undefined' || ret === null)
545 // console.log('loaded: ' + name.toString() + ' = ' + ret.toString());
550 function saveLocalStorage(name, value) {
551 // console.log('saving: ' + name.toString() + ' = ' + value.toString());
553 if(localStorageTest() === true) {
554 localStorage.setItem(name, value.toString());
563 function getTheme(def) {
564 var ret = loadLocalStorage('netdataTheme');
565 if(typeof ret === 'undefined' || ret === null || ret === 'undefined')
571 function setTheme(theme) {
572 if(theme === netdataTheme) return false;
573 return saveLocalStorage('netdataTheme', theme);
576 var netdataTheme = getTheme('slate');
577 var netdataShowHelp = true;
579 if(urlOptions.theme !== null) {
580 setTheme(urlOptions.theme);
581 netdataTheme = urlOptions.theme;
584 urlOptions.theme = netdataTheme;
586 if(urlOptions.help !== null) {
587 saveLocalStorage('options.show_help', urlOptions.help);
588 netdataShowHelp = urlOptions.help;
591 urlOptions.help = loadLocalStorage('options.show_help');
594 // --------------------------------------------------------------------
595 // registry call back to render my-netdata menu
597 var netdataRegistryCallback = function(machines_array) {
600 var found = 0, hosted = 0;
601 var len, i, url, hostname, icon;
603 if(options.hosts.length > 1) {
604 // there are mirrored hosts here
606 el += '<li><a href="#" onClick="return false;" style="color: #666;" target="_blank">databases available on this host</a></li>';
607 a1 += '<li><a href="#" onClick="return false;"><i class="fa fa-info-circle" aria-hidden="true" style="color: #666;"></i></a></li>';
609 var base = document.location.origin.toString() + document.location.pathname.toString();
610 if(base.endsWith("/host/" + options.hostname + "/"))
611 base = base.substring(0, base.length - ("/host/" + options.hostname + "/").toString().length);
613 if(base.endsWith("/"))
614 base = base.substring(0, base.length - 1);
616 var master = options.hosts[0].hostname;
617 var sorted = options.hosts.sort(function(a, b) {
618 if(a.hostname === master) return -1;
619 if(a.hostname === b.hostname) return 0;
620 else if(a.hostname > b.hostname) return 1;
627 hostname = sorted[i].hostname;
628 if(hostname == master) {
633 url = base + "/host/" + hostname + "/";
634 icon = "window-restore";
637 el += '<li id="registry_server_hosted_' + len.toString() + '"><a class="registry_link" href="' + url + '" onClick="return gotoHostedModalHandler(\'' + url + '\');">' + hostname + '</a></li>';
638 a1 += '<li id="registry_action_hosted_' + len.toString() + '"><a class="registry_link" href="' + url + '" onClick="return gotoHostedModalHandler(\'' + url + '\');"><i class="fa fa-' + icon + '" aria-hidden="true" style="color: #999;"></i></a></li>';
643 el += '<li role="separator" class="divider"></li>';
644 a1 += '<li role="separator" class="divider"></li>';
647 if(machines_array === null) {
648 var ret = loadLocalStorage("registryCallback");
649 if(typeof ret !== 'undefined' && ret !== null) {
650 machines_array = JSON.parse(ret);
651 console.log("failed to contact the registry - loaded registry data from browser local storage");
656 saveLocalStorage("registryCallback", JSON.stringify(machines_array));
658 var machines = machines_array.sort(function (a, b) {
659 if (a.name > b.name) return -1;
660 if (a.name < b.name) return 1;
664 len = machines.length;
666 var u = machines[len];
668 el += '<li id="registry_server_' + u.guid + '"><a class="registry_link" href="' + u.url + '" onClick="return gotoServerModalHandler(\'' + u.guid + '\');">' + u.name + '</a></li>';
669 a1 += '<li id="registry_action_' + u.guid + '"><a href="#" onclick="deleteRegistryModalHandler(\'' + u.guid + '\',\'' + u.name + '\',\'' + u.url + '\'); return false;"><i class="fa fa-trash-o" aria-hidden="true" style="color: #999;"></i></a></li>';
675 el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #666;" target="_blank">your netdata server list is empty...</a></li>';
677 el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #666;" target="_blank">failed to contact the registry...</a></li>';
679 a1 += '<li><a href="#" onClick="return false;"> </a></li>';
681 el += '<li role="separator" class="divider"></li>' +
682 '<li><a href="//london.netdata.rocks/default.html">UK - London (DigitalOcean.com)</a></li>' +
683 '<li><a href="//newyork.netdata.rocks/default.html">US - New York (DigitalOcean.com)</a></li>' +
684 '<li><a href="//sanfrancisco.netdata.rocks/default.html">US - San Francisco (DigitalOcean.com)</a></li>' +
685 '<li><a href="//atlanta.netdata.rocks/default.html">US - Atlanta (CDN77.com)</a></li>' +
686 '<li><a href="//frankfurt.netdata.rocks/default.html">Germany - Frankfurt (DigitalOcean.com)</a></li>' +
687 '<li><a href="//toronto.netdata.rocks/default.html">Canada - Toronto (DigitalOcean.com)</a></li>' +
688 '<li><a href="//singapore.netdata.rocks/default.html">Japan - Singapore (DigitalOcean.com)</a></li>' +
689 '<li><a href="//bangalore.netdata.rocks/default.html">India - Bangalore (DigitalOcean.com)</a></li>';
690 a1 += '<li role="separator" class="divider"></li>' +
691 '<li><a href="#"> </a></li>' +
692 '<li><a href="#"> </a></li>'+
693 '<li><a href="#"> </a></li>'+
694 '<li><a href="#"> </a></li>'+
695 '<li><a href="#"> </a></li>'+
696 '<li><a href="#"> </a></li>'+
697 '<li><a href="#"> </a></li>'+
698 '<li><a href="#"> </a></li>';
701 el += '<li role="separator" class="divider"></li>';
702 a1 += '<li role="separator" class="divider"></li>';
704 el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #999;" target="_blank">What is this?</a></li>';
705 a1 += '<li><a href="#" style="color: #999;" onclick="switchRegistryModalHandler(); return false;"><i class="fa fa-sliders" aria-hidden="true" style="color: #999;"></i></a></li>'
707 document.getElementById('mynetdata_servers').innerHTML = el;
708 document.getElementById('mynetdata_servers2').innerHTML = el;
709 document.getElementById('mynetdata_actions1').innerHTML = a1;
714 var this_is_demo = null; // FIXME
716 if(this_is_demo !== null) return this_is_demo;
717 this_is_demo = false;
720 if(typeof document.location.hostname === 'string') {
721 if(document.location.hostname.endsWith('.my-netdata.io') ||
722 document.location.hostname.endsWith('.mynetdata.io') ||
723 document.location.hostname.endsWith('.netdata.rocks') ||
724 document.location.hostname.endsWith('.firehol.org') ||
725 document.location.hostname.endsWith('.netdata.online'))
733 function netdataURL(url) {
734 if(typeof url === 'undefined')
735 url = document.location.toString();
737 if(url.indexOf('#') !== -1)
738 url = url.substring(0, url.indexOf('#'));
740 var hash = urlOptions.genHash();
742 // console.log('netdataURL: ' + url + hash);
747 function netdataReload(url) {
748 document.location = netdataURL(url);
750 // since we play with hash
751 // this is needed to reload the page
755 function gotoHostedModalHandler(url) {
756 document.location = url + urlOptions.genHash();
760 var gotoServerValidateRemaining = 0;
761 var gotoServerMiddleClick = false;
762 var gotoServerStop = false;
763 function gotoServerValidateUrl(id, guid, url) {
765 var error = 'failed';
767 if(document.location.toString().startsWith('http://') && url.toString().startsWith('https://'))
768 // we penalize https only if the current url is http
769 // to allow the user walk through all its servers.
772 else if(document.location.toString().startsWith('https://') && url.toString().startsWith('http://'))
773 error = 'can\'t check';
775 var finalURL = netdataURL(url);
777 setTimeout(function() {
778 document.getElementById('gotoServerList').innerHTML += '<tr><td style="padding-left: 20px;"><a href="' + finalURL + '" target="_blank">' + url + '</a></td><td style="padding-left: 30px;"><code id="' + guid + '-' + id + '-status">checking...</code></td></tr>';
780 NETDATA.registry.hello(url, function(data) {
781 if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid === guid) {
782 // console.log('OK ' + id + ' URL: ' + url);
783 document.getElementById(guid + '-' + id + '-status').innerHTML = "OK";
785 if(!gotoServerStop) {
786 gotoServerStop = true;
788 if(gotoServerMiddleClick) {
789 window.open(finalURL, '_blank');
790 gotoServerMiddleClick = false;
791 document.getElementById('gotoServerResponse').innerHTML = '<b>Opening new window to ' + NETDATA.registry.machines[guid].name + '<br/><a href="' + finalURL + '">' + url + '</a></b><br/>(check your pop-up blocker if it fails)';
794 document.getElementById('gotoServerResponse').innerHTML += 'found it! It is at:<br/><small>' + url + '</small>';
795 document.location = finalURL;
800 if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid !== guid)
801 error = 'wrong machine';
803 document.getElementById(guid + '-' + id + '-status').innerHTML = error;
804 gotoServerValidateRemaining--;
805 if(gotoServerValidateRemaining <= 0) {
806 gotoServerMiddleClick = false;
807 document.getElementById('gotoServerResponse').innerHTML = '<b>Sorry! I cannot find any operational URL for this server</b>';
811 }, (id * 50) + penaldy);
814 function gotoServerModalHandler(guid) {
815 // console.log('goto server: ' + guid);
817 gotoServerStop = false;
819 var len = NETDATA.registry.machines[guid].alternate_urls.length;
822 document.getElementById('gotoServerResponse').innerHTML = '';
823 document.getElementById('gotoServerList').innerHTML = '';
824 document.getElementById('gotoServerName').innerHTML = NETDATA.registry.machines[guid].name;
825 $('#gotoServerModal').modal('show');
827 gotoServerValidateRemaining = len;
829 var url = NETDATA.registry.machines[guid].alternate_urls[len];
831 gotoServerValidateUrl(count++, guid, url);
834 setTimeout(function() {
835 if(gotoServerStop === false) {
836 document.getElementById('gotoServerResponse').innerHTML = '<b>Added all the known URLs for this machine.</b>';
837 NETDATA.registry.search(guid, function(data) {
838 // console.log(data);
839 len = data.urls.length;
841 var url = data.urls[len][1];
843 if(typeof checked[url] === 'undefined') {
844 gotoServerValidateRemaining++;
846 gotoServerValidateUrl(count++, guid, url);
855 function gotoServerInit() {
856 $(".registry_link").on('click', function(e) {
859 gotoServerMiddleClick = true;
862 gotoServerMiddleClick = false;
869 function switchRegistryModalHandler() {
870 document.getElementById('switchRegistryPersonGUID').value = NETDATA.registry.person_guid;
871 document.getElementById('switchRegistryURL').innerHTML = NETDATA.registry.server;
872 document.getElementById('switchRegistryResponse').innerHTML = '';
873 $('#switchRegistryModal').modal('show');
876 function notifyForSwitchRegistry() {
877 var n = document.getElementById('switchRegistryPersonGUID').value;
879 if(n !== '' && n.length === 36) {
880 NETDATA.registry.switch(n, function(result) {
881 if(result !== null) {
882 $('#switchRegistryModal').modal('hide');
883 NETDATA.registry.init();
886 document.getElementById('switchRegistryResponse').innerHTML = "<b>Sorry! The registry rejected your request.</b>";
891 document.getElementById('switchRegistryResponse').innerHTML = "<b>The ID you have entered is not a GUID.</b>";
894 var deleteRegistryUrl = null;
895 function deleteRegistryModalHandler(guid, name, url) {
898 deleteRegistryUrl = url;
899 document.getElementById('deleteRegistryServerName').innerHTML = name;
900 document.getElementById('deleteRegistryServerName2').innerHTML = name;
901 document.getElementById('deleteRegistryServerURL').innerHTML = url;
902 document.getElementById('deleteRegistryResponse').innerHTML = '';
903 $('#deleteRegistryModal').modal('show');
906 function notifyForDeleteRegistry() {
907 if(deleteRegistryUrl) {
908 NETDATA.registry.delete(deleteRegistryUrl, function(result) {
909 if(result !== null) {
910 deleteRegistryUrl = null;
911 $('#deleteRegistryModal').modal('hide');
912 NETDATA.registry.init();
915 document.getElementById('deleteRegistryResponse').innerHTML = "<b>Sorry! this command was rejected by the registry server.</b>";
925 hostname: 'netdata_server', // will be overwritten by the netdata server
934 // chartsMinWidth: 1450,
938 function chartsPerRow(total) {
939 if(options.chartsPerRow === 0) {
941 //var width = Math.floor(total / options.chartsMinWidth);
942 //if(width === 0) width = 1;
945 else return options.chartsPerRow;
948 function prioritySort(a, b) {
949 if(a.priority < b.priority) return -1;
950 if(a.priority > b.priority) return 1;
951 if(a.name < b.name) return -1;
955 function sortObjectByPriority(object) {
959 for(var i in object) {
960 if(!object.hasOwnProperty(i)) continue;
962 if(typeof idx[i] === 'undefined') {
968 sorted.sort(function(a, b) {
969 if(idx[a].priority < idx[b].priority) return -1;
970 if(idx[a].priority > idx[b].priority) return 1;
979 // ----------------------------------------------------------------------------
980 // scroll to a section, without changing the browser history
982 function scrollToId(hash) {
983 if(hash && hash != '' && document.getElementById(hash) !== null) {
984 var offset = $('#' + hash).offset();
985 if(typeof offset !== 'undefined')
986 $('html, body').animate({ scrollTop: offset.top }, 0);
989 // we must return false to prevent the default action
993 // ----------------------------------------------------------------------------
995 // user editable information
996 var customDashboard = {
1002 // netdata standard information
1003 var netdataDashboard = {
1004 sparklines_registry: {},
1011 // generate a sparkline
1012 // used in the documentation
1013 sparkline: function (prefix, chart, dimension, units, suffix) {
1014 if(options.data === null || typeof options.data.charts === 'undefined')
1017 if(typeof options.data.charts[chart] === 'undefined')
1020 if(typeof options.data.charts[chart].dimensions === 'undefined')
1023 if(typeof options.data.charts[chart].dimensions[dimension] === 'undefined')
1026 var key = chart + '.' + dimension;
1028 if(typeof units === 'undefined')
1031 if(typeof this.sparklines_registry[key] === 'undefined')
1032 this.sparklines_registry[key] = { count: 1 };
1034 this.sparklines_registry[key].count++;
1036 key = key + '.' + this.sparklines_registry[key].count;
1038 return prefix + '<div data-netdata="' + chart + '" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dimensions="' + dimension + '" data-show-value-of-' + dimension + '-at="' + key + '"></div> (<span id="' + key + '" style="display: inline-block; min-width: 50px; text-align: right;">X</span>' + units + ')' + suffix;
1041 gaugeChart: function(title, width, dimensions, colors) {
1042 if(typeof colors === 'undefined')
1045 if(typeof dimensions === 'undefined')
1048 return '<div data-netdata="CHART_UNIQUE_ID"'
1049 + ' data-dimensions="' + dimensions + '"'
1050 + ' data-chart-library="gauge"'
1051 + ' data-gauge-adjust="width"'
1052 + ' data-title="' + title + '"'
1053 + ' data-width="' + width + '"'
1054 + ' data-before="0"'
1055 + ' data-after="-CHART_DURATION"'
1056 + ' data-points="CHART_DURATION"'
1057 + ' data-colors="' + colors + '"'
1058 + ' role="application"></div>';
1061 anyAttribute: function(obj, attr, key, def) {
1062 if(typeof(obj[key]) !== 'undefined') {
1063 var x = obj[key][attr];
1065 if(typeof(x) === 'undefined')
1068 if(typeof(x) === 'function') {
1069 return x(netdataDashboard.os);
1078 menuTitle: function(chart) {
1079 if(typeof chart.menu_pattern !== 'undefined') {
1080 return (this.anyAttribute(this.menu, 'title', chart.menu_pattern, chart.menu_pattern).toString()
1081 + ' ' + chart.type.slice(-(chart.type.length - chart.menu_pattern.length - 1)).toString()).replace(/_/g, ' ');
1084 return (this.anyAttribute(this.menu, 'title', chart.menu, chart.menu)).toString().replace(/_/g, ' ');
1087 menuIcon: function(chart) {
1088 if(typeof chart.menu_pattern !== 'undefined')
1089 return this.anyAttribute(this.menu, 'icon', chart.menu_pattern, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>').toString();
1091 return this.anyAttribute(this.menu, 'icon', chart.menu, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>');
1094 menuInfo: function(chart) {
1095 if(typeof chart.menu_pattern !== 'undefined')
1096 return this.anyAttribute(this.menu, 'info', chart.menu_pattern, null);
1098 return this.anyAttribute(this.menu, 'info', chart.menu, null);
1101 menuHeight: function(chart) {
1102 if(typeof chart.menu_pattern !== 'undefined')
1103 return this.anyAttribute(this.menu, 'height', chart.menu_pattern, 1.0);
1105 return this.anyAttribute(this.menu, 'height', chart.menu, 1.0);
1108 submenuTitle: function(menu, submenu) {
1109 var key = menu + '.' + submenu;
1110 // console.log(key);
1111 var title = this.anyAttribute(this.submenu, 'title', key, submenu).toString().replace(/_/g, ' ');
1112 if(title.length > 28) {
1113 var a = title.substring(0, 13);
1114 var b = title.substring(title.length - 12, title.length);
1115 return a + '...' + b;
1120 submenuInfo: function(menu, submenu) {
1121 var key = menu + '.' + submenu;
1122 return this.anyAttribute(this.submenu, 'info', key, null);
1125 submenuHeight: function(menu, submenu, relative) {
1126 var key = menu + '.' + submenu;
1127 return this.anyAttribute(this.submenu, 'height', key, 1.0) * relative;
1130 contextInfo: function(id) {
1131 var x = this.anyAttribute(this.context, 'info', id, null);
1134 return '<div class="chart-message netdata-chart-alignment" role="document">' + x + '</div>';
1139 contextValueRange: function(id) {
1140 if(typeof this.context[id] !== 'undefined' && typeof this.context[id].valueRange !== 'undefined')
1141 return this.context[id].valueRange;
1143 return '[null, null]';
1146 contextHeight: function(id, def) {
1147 if(typeof this.context[id] !== 'undefined' && typeof this.context[id].height !== 'undefined')
1148 return def * this.context[id].height;
1154 // ----------------------------------------------------------------------------
1156 // enrich the data structure returned by netdata
1157 // to reflect our menu system and content
1158 // FIXME: this is a shame - we should fix charts naming (issue #807)
1159 function enrichChartData(chart) {
1160 var parts = chart.type.split('_');
1171 chart.menu = chart.type;
1172 if(parts.length > 2 && parts[1] === 'cache')
1173 chart.menu_pattern = tmp + '_' + parts[1];
1174 else if(parts.length > 1)
1175 chart.menu_pattern = tmp;
1179 chart.menu = chart.type;
1180 if(parts.length > 2 && parts[1] === 'rndc')
1181 chart.menu_pattern = tmp + '_' + parts[1];
1182 else if(parts.length > 1)
1183 chart.menu_pattern = tmp;
1187 chart.menu = chart.type;
1188 if(chart.id.match(/.*[\._\/-:]qemu[\._\/-:]*/) || chart.id.match(/.*[\._\/-:]kvm[\._\/-:]*/))
1189 chart.menu_pattern = 'cgqemu';
1191 chart.menu_pattern = 'cgroup';
1195 chart.menu = chart.type;
1196 if(parts.length > 2 && parts[1] === 'dhcpd')
1197 chart.menu_pattern = tmp + '_' + parts[1];
1198 else if(parts.length > 1)
1199 chart.menu_pattern = tmp;
1203 chart.menu = chart.type;
1204 if(parts.length > 3 && parts[1] === 'status' && parts[2] === 'log')
1205 chart.menu_pattern = tmp + '_' + parts[1];
1206 else if(parts.length > 1)
1207 chart.menu_pattern = tmp;
1212 chart.menu = chart.type;
1213 if(parts.length > 2 && parts[1] === 'log')
1214 chart.menu_pattern = tmp + '_' + parts[1];
1215 else if(parts.length > 1)
1216 chart.menu_pattern = tmp;
1222 // find a name for this device from fireqos info
1223 // we strip '_(in|out)' or '(in|out)_'
1224 if(chart.context === 'tc.qos' && (typeof options.submenu_names[chart.family] === 'undefined' || options.submenu_names[chart.family] === chart.family)) {
1225 var n = chart.name.split('.')[1];
1226 if(n.endsWith('_in'))
1227 options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_in'));
1228 else if(n.endsWith('_out'))
1229 options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_out'));
1230 else if(n.startsWith('in_'))
1231 options.submenu_names[chart.family] = n.slice(3, n.length);
1232 else if(n.startsWith('out_'))
1233 options.submenu_names[chart.family] = n.slice(4, n.length);
1235 options.submenu_names[chart.family] = n;
1238 // increase the priority of IFB devices
1239 // to have inbound appear before outbound
1240 if(chart.id.match(/.*-ifb$/))
1246 chart.menu = chart.type;
1247 if(parts.length > 1)
1248 chart.menu_pattern = tmp;
1252 chart.submenu = chart.family;
1255 // ----------------------------------------------------------------------------
1257 function headMain(os, charts, duration) {
1262 if(typeof charts['system.swap'] !== 'undefined')
1263 head += '<div style="margin-right: 10px;" data-netdata="system.swap"'
1264 + ' data-dimensions="used"'
1265 + ' data-append-options="percentage"'
1266 + ' data-chart-library="easypiechart"'
1267 + ' data-title="Used Swap"'
1269 + ' data-easypiechart-max-value="100"'
1270 + ' data-width="8%"'
1271 + ' data-before="0"'
1272 + ' data-after="-' + duration.toString() + '"'
1273 + ' data-points="' + duration.toString() + '"'
1274 + ' data-colors="#DD4400"'
1275 + ' role="application"></div>';
1277 if(typeof charts['system.io'] !== 'undefined') {
1278 head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1279 + ' data-dimensions="in"'
1280 + ' data-chart-library="easypiechart"'
1281 + ' data-title="Disk Read"'
1282 + ' data-width="10%"'
1283 + ' data-before="0"'
1284 + ' data-after="-' + duration.toString() + '"'
1285 + ' data-points="' + duration.toString() + '"'
1286 + ' role="application"></div>';
1288 head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1289 + ' data-dimensions="out"'
1290 + ' data-chart-library="easypiechart"'
1291 + ' data-title="Disk Write"'
1292 + ' data-width="10%"'
1293 + ' data-before="0"'
1294 + ' data-after="-' + duration.toString() + '"'
1295 + ' data-points="' + duration.toString() + '"'
1296 + ' role="application"></div>';
1299 if(typeof charts['system.cpu'] !== 'undefined')
1300 head += '<div data-netdata="system.cpu"'
1301 + ' data-chart-library="gauge"'
1302 + ' data-title="CPU"'
1304 + ' data-gauge-max-value="100"'
1305 + ' data-width="18%"'
1306 + ' data-after="-' + duration.toString() + '"'
1307 + ' data-points="' + duration.toString() + '"'
1308 + ' data-colors="' + NETDATA.colors[12] + '"'
1309 + ' role="application"></div>';
1311 if(typeof charts['system.ipv4'] !== 'undefined') {
1312 head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1313 + ' data-dimensions="received"'
1314 + ' data-chart-library="easypiechart"'
1315 + ' data-title="IPv4 Inbound"'
1316 + ' data-width="10%"'
1317 + ' data-before="0"'
1318 + ' data-after="-' + duration.toString() + '"'
1319 + ' data-points="' + duration.toString() + '"'
1320 + ' role="application"></div>';
1322 head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1323 + ' data-dimensions="sent"'
1324 + ' data-chart-library="easypiechart"'
1325 + ' data-title="IPv4 Outbound"'
1326 + ' data-width="10%"'
1327 + ' data-before="0"'
1328 + ' data-after="-' + duration.toString() + '"'
1329 + ' data-points="' + duration.toString() + '"'
1330 + ' role="application"></div>';
1332 else if(typeof charts['system.ipv6'] !== 'undefined') {
1333 head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"'
1334 + ' data-dimensions="received"'
1335 + ' data-chart-library="easypiechart"'
1336 + ' data-title="IPv6 Inbound"'
1337 + ' data-units="kbps"'
1338 + ' data-width="10%"'
1339 + ' data-before="0"'
1340 + ' data-after="-' + duration.toString() + '"'
1341 + ' data-points="' + duration.toString() + '"'
1342 + ' role="application"></div>';
1344 head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"'
1345 + ' data-dimensions="sent"'
1346 + ' data-chart-library="easypiechart"'
1347 + ' data-title="IPv6 Outbound"'
1348 + ' data-units="kbps"'
1349 + ' data-width="10%"'
1350 + ' data-before="0"'
1351 + ' data-after="-' + duration.toString() + '"'
1352 + ' data-points="' + duration.toString() + '"'
1353 + ' role="application"></div>';
1356 if(typeof charts['system.ram'] !== 'undefined')
1357 head += '<div style="margin-right: 10px;" data-netdata="system.ram"'
1358 + ' data-dimensions="used|buffers|active|wired"' // active and wired are FreeBSD stats
1359 + ' data-append-options="percentage"'
1360 + ' data-chart-library="easypiechart"'
1361 + ' data-title="Used RAM"'
1363 + ' data-easypiechart-max-value="100"'
1364 + ' data-width="8%"'
1365 + ' data-after="-' + duration.toString() + '"'
1366 + ' data-points="' + duration.toString() + '"'
1367 + ' data-colors="' + NETDATA.colors[7] + '"'
1368 + ' role="application"></div>';
1373 function generateHeadCharts(type, chart, duration) {
1375 var hcharts = netdataDashboard.anyAttribute(netdataDashboard.context, type, chart.context, []);
1376 if(hcharts.length > 0) {
1377 var hi = 0, hlen = hcharts.length;
1379 if(typeof hcharts[hi] === 'function')
1380 head += hcharts[hi](netdataDashboard.os, chart.id).replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id);
1382 head += hcharts[hi].replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id);
1389 function renderPage(menus, data) {
1390 var div = document.getElementById('charts_div');
1391 var pcent_width = Math.floor(100 / chartsPerRow($(div).width()));
1393 // find the proper duration for per-second updates
1394 var duration = Math.round(($(div).width() * pcent_width / 100 * data.update_every / 3) / 60) * 60;
1396 var sidebar = '<ul class="nav dashboard-sidenav" data-spy="affix" id="sidebar_ul">';
1397 var mainhead = headMain(netdataDashboard.os, data.charts, duration);
1400 var main = sortObjectByPriority(menus);
1401 var i = 0, len = main.length;
1403 var menu = main[i++];
1405 // generate an entry at the main menu
1407 var menuid = NETDATA.name2id('menu_' + menu);
1408 sidebar += '<li class=""><a href="#' + menuid + '" onClick="return scrollToId(\'' + menuid + '\');">' + menus[menu].icon + ' ' + menus[menu].title + '</a><ul class="nav">';
1409 html += '<div role="section"><div role="sectionhead"><h1 id="' + menuid + '" role="heading">' + menus[menu].title + '</h1></div><div role="document">';
1411 if(menus[menu].info !== null)
1412 html += menus[menu].info;
1414 // console.log(' >> ' + menu + ' (' + menus[menu].priority + '): ' + menus[menu].title);
1417 var mhead = '<div class="netdata-chart-row">' + mainhead;
1420 // sort the submenus of this menu
1421 var sub = sortObjectByPriority(menus[menu].submenus);
1422 var si = 0, slen = sub.length;
1424 var submenu = sub[si++];
1426 // generate an entry at the submenu
1427 var submenuid = NETDATA.name2id('menu_' + menu + '_submenu_' + submenu);
1428 sidebar += '<li class><a href="#' + submenuid + '" onClick="return scrollToId(\'' + submenuid + '\');">' + menus[menu].submenus[submenu].title + '</a></li>';
1429 shtml += '<div class="netdata-group-container" id="' + submenuid + '" style="display: inline-block; width: ' + pcent_width.toString() + '%"><h2 id="' + submenuid + '" class="netdata-chart-alignment" role="heading">' + menus[menu].submenus[submenu].title + '</h2>';
1431 if(menus[menu].submenus[submenu].info !== null)
1432 shtml += '<div class="chart-message netdata-chart-alignment" role="document">' + menus[menu].submenus[submenu].info + '</div>';
1434 var head = '<div class="netdata-chart-row">';
1437 // console.log(' \------- ' + submenu + ' (' + menus[menu].submenus[submenu].priority + '): ' + menus[menu].submenus[submenu].title);
1439 // sort the charts in this submenu of this menu
1440 menus[menu].submenus[submenu].charts.sort(prioritySort);
1441 var ci = 0, clen = menus[menu].submenus[submenu].charts.length;
1443 var chart = menus[menu].submenus[submenu].charts[ci++];
1445 // generate the submenu heading charts
1446 mhead += generateHeadCharts('mainheads', chart, duration);
1447 head += generateHeadCharts('heads', chart, duration);
1449 // generate the chart
1450 chtml += netdataDashboard.contextInfo(chart.context) + '<div id="chart_' + NETDATA.name2id(chart.id) + '" data-netdata="' + chart.id + '"'
1451 + ' data-width="' + pcent_width.toString() + '%"'
1452 + ' data-height="' + netdataDashboard.contextHeight(chart.context, options.chartsHeight).toString() + 'px"'
1453 + ' data-dygraph-valuerange="' + netdataDashboard.contextValueRange(chart.context) + '"'
1454 + ' data-before="0"'
1455 + ' data-after="-' + duration.toString() + '"'
1456 + ' data-id="' + NETDATA.name2id(options.hostname + '/' + chart.id) + '"'
1457 + ' data-colors="' + netdataDashboard.anyAttribute(netdataDashboard.context, 'colors', chart.context, '') + '"'
1458 + ' role="application"></div>';
1460 // console.log(' \------- ' + chart.id + ' (' + chart.priority + '): ' + chart.context + ' height: ' + menus[menu].submenus[submenu].height);
1464 shtml += head + chtml + '</div>';
1468 sidebar += '</ul></li>';
1469 html += mhead + shtml + '</div></div><hr role="separator"/>';
1472 sidebar += '<li class="" style="padding-top:15px;"><a href="https://github.com/firehol/netdata/wiki/Add-more-charts-to-netdata" target="_blank"><i class="fa fa-plus" aria-hidden="true"></i> add more charts</a></li>';
1473 sidebar += '<li class=""><a href="https://github.com/firehol/netdata/wiki/Add-more-alarms-to-netdata" target="_blank"><i class="fa fa-plus" aria-hidden="true"></i> add more alarms</a></li>';
1474 sidebar += '<li class="" style="margin:20px;color:#666;"><small>netdata on <b>' + data.hostname.toString() + '</b>, collects every ' + ((data.update_every == 1)?'second':data.update_every.toString() + ' seconds') + ' <b>' + data.dimensions_count.toLocaleString() + '</b> metrics, presented as <b>' + data.charts_count.toLocaleString() + '</b> charts and monitored by <b>' + data.alarms_count.toLocaleString() + '</b> alarms, using ' + Math.round(data.rrd_memory_bytes / 1024 / 1024).toLocaleString() + ' MB of memory for ' + seconds4human(data.update_every * data.history) + ' of real-time history.<br/> <br/><b>netdata</b><br/>v' + data.version.toString() +'</small></li>';
1476 div.innerHTML = html;
1477 document.getElementById('sidebar').innerHTML = sidebar;
1481 function renderChartsAndMenu(data) {
1482 var menus = options.menus;
1483 var charts = data.charts;
1486 for(var c in charts) {
1487 if(!charts.hasOwnProperty(c)) continue;
1489 var chart = charts[c];
1490 enrichChartData(chart);
1494 if(typeof menus[m] === 'undefined') {
1496 menu_pattern: chart.menu_pattern,
1497 priority: chart.priority,
1499 title: netdataDashboard.menuTitle(chart),
1500 icon: netdataDashboard.menuIcon(chart),
1501 info: netdataDashboard.menuInfo(chart),
1502 height: netdataDashboard.menuHeight(chart) * options.chartsHeight
1506 if(typeof(menus[m].menu_pattern) === 'undefined')
1507 menus[m].menu_pattern = chart.menu_pattern;
1509 if(chart.priority < menus[m].priority)
1510 menus[m].priority = chart.priority;
1513 menu_key = (typeof(menus[m].menu_pattern) !== 'undefined')?menus[m].menu_pattern:m;
1515 // create the submenu
1516 if(typeof menus[m].submenus[chart.submenu] === 'undefined') {
1517 menus[m].submenus[chart.submenu] = {
1518 priority: chart.priority,
1521 info: netdataDashboard.submenuInfo(menu_key, chart.submenu),
1522 height: netdataDashboard.submenuHeight(menu_key, chart.submenu, menus[m].height)
1526 if (chart.priority < menus[m].submenus[chart.submenu].priority)
1527 menus[m].submenus[chart.submenu].priority = chart.priority;
1530 // index the chart in the menu/submenu
1531 menus[m].submenus[chart.submenu].charts.push(chart);
1534 // propagate the descriptive subname given to QoS
1535 // to all the other submenus with the same name
1537 if(!menus.hasOwnProperty(m)) continue;
1539 for(var s in menus[m].submenus) {
1540 if(!menus[m].submenus.hasOwnProperty(s)) continue;
1542 // set the family using a name
1543 if(typeof options.submenu_names[s] !== 'undefined') {
1544 menus[m].submenus[s].title = s + ' (' + options.submenu_names[s] + ')';
1547 menu_key = (typeof(menus[m].menu_pattern) !== 'undefined')?menus[m].menu_pattern:m;
1548 menus[m].submenus[s].title = netdataDashboard.submenuTitle(menu_key, s);
1553 renderPage(menus, data);
1556 // ----------------------------------------------------------------------------
1558 function loadJs(url, callback) {
1563 xhrFields: { withCredentials: true } // required for the cookie
1566 alert('Cannot load required JS library: ' + url);
1568 .always(function() {
1569 if(typeof callback === 'function')
1574 var bootstrapTableLoaded = false;
1575 function loadBootstrapTable(callback) {
1576 if(bootstrapTableLoaded === false) {
1577 bootstrapTableLoaded = true;
1578 loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-1.11.0.min.js', function() {
1579 loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-export-1.11.0.min.js', function() {
1580 loadJs(NETDATA.serverDefault + 'lib/tableExport-1.6.0.min.js', callback);
1587 function alarmsUpdateModal() {
1588 var active = '<h3>Raised Alarms</h3><table class="table">';
1589 var all = '<h3>All Running Alarms</h3><div class="panel-group" id="alarms_all_accordion" role="tablist" aria-multiselectable="true">';
1590 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> red </b></span> is critical, <span style="color:#fe7d37"><b> orange </b></span> is warning, <span style="color: #4c1"><b> bright green </b></span> is ok, <span style="color: #9f9f9f"><b> light grey </b></span> is undefined (i.e. no data or no status), <span style="color: #000"><b> black </b></span> is not initialized. You can copy and paste their URLs to embed them in any web page.<br/>netdata can send notifications for these alarms. Check <a href="https://github.com/firehol/netdata/blob/master/conf.d/health_alarm_notify.conf">this configuration file</a> for more information.';
1592 NETDATA.alarms.get('all', function(data) {
1593 options.alarm_families = [];
1595 alarmsCallback(data);
1598 document.getElementById('alarms_active').innerHTML =
1599 document.getElementById('alarms_all').innerHTML =
1600 document.getElementById('alarms_log').innerHTML =
1601 'failed to load alarm data!';
1605 function alarmid4human(id) {
1609 return id.toString();
1612 function timestamp4human(timestamp, space) {
1616 if(typeof space === 'undefined')
1619 var t = new Date(timestamp * 1000);
1620 var now = new Date();
1622 if(t.toDateString() == now.toDateString())
1623 return t.toLocaleTimeString();
1625 return t.toLocaleDateString() + space + t.toLocaleTimeString();
1628 function alarm_lookup_explain(alarm, chart) {
1629 var dimensions = ' of all values ';
1631 if(chart.dimensions.length > 1)
1632 dimensions = ' of the sum of all dimensions ';
1634 if(typeof alarm.lookup_dimensions !== 'undefined') {
1635 var d = alarm.lookup_dimensions.replace('|', ',');
1636 var x = d.split(',');
1638 dimensions = 'of the sum of dimensions <code>' + alarm.lookup_dimensions + '</code> ';
1640 dimensions = 'of all values of dimension <code>' + alarm.lookup_dimensions + '</code> ';
1643 return '<code>' + alarm.lookup_method + '</code> '
1644 + dimensions + ', of chart <code>' + alarm.chart + '</code>'
1645 + ', starting <code>' + seconds4human(alarm.lookup_after + alarm.lookup_before) + '</code> and up to <code>' + seconds4human(alarm.lookup_before) + '</code>'
1646 + ((alarm.lookup_options)?(', with options <code>' + alarm.lookup_options.replace(' ', ', ') + '</code>'):'')
1650 function alarm_to_html(alarm, full) {
1651 var chart = options.data.charts[alarm.chart];
1652 if(typeof(chart) === 'undefined') {
1653 // this means the charts loaded are incomplete
1654 // probably netdata was restarted and more charts
1655 // are now available.
1659 var has_alarm = (typeof alarm.warn !== 'undefined' || typeof alarm.crit !== 'undefined');
1661 var role_href = ((has_alarm === true)?('<br/> <br/>role: <b>' + alarm.recipient + '</b><br/> <br/><b><i class="fa fa-line-chart" aria-hidden="true"></i></b><small> <a href="#" onClick="NETDATA.alarms.scrollToChart(\'' + alarm.chart + '\'); $(\'#alarmsModal\').modal(\'hide\'); return false;">jump to chart</a></small>'):(' '));
1663 var html = '<tr><td class="text-center" style="vertical-align:middle" width="40%"><b>' + alarm.chart + '</b><br/> <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/> <br/><span style="font-size: 18px">' + alarm.info + '</span>' + role_href + '</td>'
1664 + '<td><table class="table">'
1665 + ((typeof alarm.warn !== 'undefined')?('<tr><td width="10%" style="text-align:right">warning when</td><td><span style="font-family: monospace; color:#fe7d37; font-weight: bold;">' + alarm.warn + '</span></td></tr>'):'')
1666 + ((typeof alarm.crit !== 'undefined')?('<tr><td width="10%" style="text-align:right">critical when</td><td><span style="font-family: monospace; color: #e05d44; font-weight: bold;">' + alarm.crit + '</span></td></tr>'):'');
1669 var units = chart.units;
1670 if(units === '%') units = '%';
1672 html += ((typeof alarm.lookup_after !== 'undefined')?('<tr><td width="10%" style="text-align:right">db lookup</td><td>' + alarm_lookup_explain(alarm, chart) + '</td></tr>'):'')
1673 + ((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>'):'')
1674 + ((chart.green !== null)?('<tr><td width="10%" style="text-align:right">green threshold</td><td><code>' + chart.green + ' ' + units + '</code></td></tr>'):'')
1675 + ((chart.red !== null)?('<tr><td width="10%" style="text-align:right">red threshold</td><td><code>' + chart.red + ' ' + units + '</code></td></tr>'):'');
1679 if((alarm.delay_up_duration > 0 || alarm.delay_down_duration > 0) && alarm.delay_multiplier != 0 && alarm.delay_max_duration > 0) {
1680 if(alarm.delay_up_duration == alarm.delay_down_duration) {
1681 delay += '<small><br/>hysteresis ' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' });
1684 delay = '<small><br/>hysteresis ';
1685 if(alarm.delay_up_duration > 0) {
1686 delay += 'on escalation <code>' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' }) + '</code>, ';
1688 if(alarm.delay_down_duration > 0) {
1689 delay += 'on recovery <code>' + seconds4human(alarm.delay_down_duration, { negative_suffix: '' }) + '</code>, ';
1692 if(alarm.delay_multiplier != 1.0) {
1693 delay += 'multiplied by <code>' + alarm.delay_multiplier.toString() + '</code>';
1694 delay += ', up to <code>' + seconds4human(alarm.delay_max_duration, { negative_suffix: '' }) + '</code>';
1696 delay += '</small>';
1699 html += '<tr><td width="10%" style="text-align:right">check every</td><td>' + seconds4human(alarm.update_every, { negative_suffix: '' }) + '</td></tr>'
1700 + ((has_alarm === true)?('<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span>' + delay + '</td></tr>'):'')
1701 + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>'
1702 + '</table></td></tr>';
1707 function alarm_family_show(id) {
1708 var html = '<table class="table">';
1709 var family = options.alarm_families[id];
1710 var len = family.arr.length;
1712 var alarm = family.arr[len];
1713 html += alarm_to_html(alarm, true);
1717 $('#alarm_all_' + id.toString()).html(html);
1720 // find the proper family of each alarm
1721 var now = Date.now();
1722 var x, family, alarm;
1723 var count_active = 0;
1726 var families_sort = [];
1727 for(x in data.alarms) {
1728 if(!data.alarms.hasOwnProperty(x)) continue;
1730 alarm = data.alarms[x];
1731 family = alarm.family;
1734 var chart = options.data.charts[alarm.chart];
1735 if(typeof chart === 'undefined')
1736 chart = options.data.charts_by_name[alarm.chart];
1738 // not found - this should never happen!
1739 if(typeof chart === 'undefined') {
1740 console.log('WARNING: alarm ' + x + ' is linked to chart ' + alarm.chart + ', which is not found in the list of chart got from the server.');
1741 chart = { priority: 9999999 };
1743 else if(typeof chart.menu !== 'undefined' && typeof chart.submenu !== 'undefined')
1744 // the family based on the chart
1745 family = chart.menu + ' - ' + chart.submenu;
1747 if(typeof families[family] === 'undefined') {
1748 families[family] = {
1751 priority: chart.priority
1754 families_sort.push(families[family]);
1757 if(chart.priority < families[family].priority)
1758 families[family].priority = chart.priority;
1760 families[family].arr.unshift(alarm);
1763 // sort the families, like the dashboard menu does
1764 var families_sorted = families_sort.sort(function (a, b) {
1765 if (a.priority > b.priority) return -1;
1766 if (a.priority < b.priority) return 1;
1771 var len = families_sorted.length;
1773 family = families_sorted[len].name;
1774 var active_family_added = false;
1775 var expanded = 'true';
1780 all += "</table></div></div></div>";
1782 collapsed = 'class="collapsed"';
1786 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() + '">';
1788 options.alarm_families[fc] = families[family];
1792 var arr = families[family].arr;
1796 if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') {
1797 if(!active_family_added) {
1798 active_family_added = true;
1799 active += '<tr><th class="text-center" colspan="2"><h4>' + family + '</h4></th></tr>';
1802 active += alarm_to_html(alarm, true);
1808 active += "</table>";
1809 if(families_sorted.length > 0) all += "</div></div></div>";
1813 active += "<h4>Everything is normal. No raised alarms.</h4>";
1818 all += "<h4>No alarms are running in this system.</h4>";
1822 document.getElementById('alarms_active').innerHTML = active;
1823 document.getElementById('alarms_all').innerHTML = all;
1825 if(families_sorted.length > 0) alarm_family_show(0);
1827 // register bootstrap events
1828 var $accordion = $('#alarms_all_accordion');
1829 $accordion.on('show.bs.collapse', function (d) {
1830 var target = $(d.target);
1831 var id = $(target).data('alarm-id');
1832 alarm_family_show(id);
1834 $accordion.on('hidden.bs.collapse', function (d) {
1835 var target = $(d.target);
1836 var id = $(target).data('alarm-id');
1837 $('#alarm_all_' + id.toString()).html('');
1840 document.getElementById('alarms_log').innerHTML = '<h3>Alarm Log</h3><table id="alarms_log_table"></table>';
1842 loadBootstrapTable(function () {
1843 $('#alarms_log_table').bootstrapTable({
1844 url: NETDATA.alarms.server + '/api/v1/alarm_log?all',
1848 showPaginationSwitch: false,
1851 searchAlign: 'left',
1854 exportDataType: 'basic',
1856 fileName: 'netdata_alarm_log'
1858 rowStyle: function(row, index) {
1861 switch(row.status) {
1862 case 'CRITICAL' : return { classes: 'danger' }; break;
1863 case 'WARNING' : return { classes: 'warning' }; break;
1864 case 'UNDEFINED': return { classes: 'info' }; break;
1865 case 'CLEAR' : return { classes: 'success' }; break;
1878 title: 'Event Date',
1880 titleTooltip: 'The date and time the even took place',
1881 formatter: function(value, row, index) { void(row); void(index); return timestamp4human(value, ' '); },
1890 titleTooltip: 'The host that generated this event',
1898 titleTooltip: 'The host unique ID for this event',
1899 formatter: function(value, row, index) { void(row); void(index); return alarmid4human(value); },
1908 titleTooltip: 'The ID of the alarm that generated this event',
1909 formatter: function(value, row, index) { void(row); void(index); return alarmid4human(value); },
1916 field: 'alarm_event_id',
1917 title: 'Alarm Event ID',
1918 titleTooltip: 'The incremental ID of this event for the given alarm',
1919 formatter: function(value, row, index) { void(row); void(index); return alarmid4human(value); },
1928 titleTooltip: 'The chart the alarm is attached to',
1937 titleTooltip: 'The family of the chart the alarm is attached to',
1946 titleTooltip: 'The alarm name that generated this event',
1947 formatter: function(value, row, index) {
1950 return value.toString().replace(/_/g, ' ');
1958 field: 'value_string',
1959 title: 'Friendly Value',
1960 titleTooltip: 'The value of the alarm, that triggered this event',
1966 field: 'old_value_string',
1967 title: 'Friendly Old Value',
1968 titleTooltip: 'The value of the alarm, just before this event',
1977 titleTooltip: 'The value of the alarm, just before this event',
1978 formatter: function(value, row, index) {
1981 return ((value !== null)?Math.round(value * 100) / 100:'NaN').toString();
1991 titleTooltip: 'The value of the alarm, that triggered this event',
1992 formatter: function(value, row, index) {
1995 return ((value !== null)?Math.round(value * 100) / 100:'NaN').toString();
2005 titleTooltip: 'The units of the value of the alarm',
2012 field: 'old_status',
2013 title: 'Old Status',
2014 titleTooltip: 'The status of the alarm, just before this event',
2023 titleTooltip: 'The status of the alarm, that was set due to this event',
2031 title: 'Last Duration',
2032 titleTooltip: 'The duration the alarm was at its previous state, just before this event',
2033 formatter: function(value, row, index) {
2036 return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
2044 field: 'non_clear_duration',
2045 title: 'Raised Duration',
2046 titleTooltip: 'The duration the alarm was raised, just before this event',
2047 formatter: function(value, row, index) {
2050 return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
2060 titleTooltip: 'The recipient of this event',
2068 title: 'Processed Status',
2069 titleTooltip: 'True when this event is processed',
2070 formatter: function(value, row, index) {
2086 title: 'Updated Status',
2087 titleTooltip: 'True when this event has been updated by another event',
2088 formatter: function(value, row, index) {
2103 field: 'updated_by_id',
2104 title: 'Updated By ID',
2105 titleTooltip: 'The unique ID of the event that obsoleted this one',
2106 formatter: function(value, row, index) { void(row); void(index); return alarmid4human(value); },
2113 field: 'updates_id',
2114 title: 'Updates ID',
2115 titleTooltip: 'The unique ID of the event obsoleted because of this event',
2116 formatter: function(value, row, index) { void(row); void(index); return alarmid4human(value); },
2125 titleTooltip: 'The script to handle the event notification',
2133 title: 'Script Run At',
2134 titleTooltip: 'The date and time the script has been ran',
2135 formatter: function(value, row, index) { void(row); void(index); return timestamp4human(value, ' '); },
2143 title: 'Script Return Value',
2144 titleTooltip: 'The return code of the script',
2145 formatter: function(value, row, index) {
2150 return 'OK (returned 0)';
2152 return 'FAILED (with code ' + value.toString() + ')';
2161 title: 'Script Delay',
2162 titleTooltip: 'The hysteresis of the notification',
2163 formatter: function(value, row, index) {
2167 return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
2175 field: 'delay_up_to_timestamp',
2176 title: 'Script Delay Run At',
2177 titleTooltip: 'The date and time the script should be run, after hysteresis',
2178 formatter: function(value, row, index) { void(row); void(index); return timestamp4human(value, ' '); },
2186 title: 'Description',
2187 titleTooltip: 'A short description of the alarm',
2195 title: 'Alarm Source',
2196 titleTooltip: 'The source of configuration of the alarm',
2204 // console.log($('#alarms_log_table').bootstrapTable('getOptions'));
2209 function seconds4human(seconds, options) {
2210 var default_options = {
2213 negative_suffix: 'ago',
2223 if(typeof options !== 'object')
2224 options = default_options;
2227 for(x in default_options) {
2228 if(typeof options[x] !== 'string')
2229 options[x] = default_options[x];
2233 if(typeof seconds === 'string')
2234 seconds = parseInt(seconds);
2242 if(options.negative_suffix !== '') suffix = options.space + options.negative_suffix;
2245 var hours = Math.floor(seconds / 3600);
2246 seconds -= (hours * 3600);
2248 var minutes = Math.floor(seconds / 60);
2249 seconds -= (minutes * 60);
2253 if(hours > 1) txt += hours.toString() + options.space + options.hours;
2254 else if(hours === 1) txt += hours.toString() + options.space + options.hour;
2256 if(hours > 0 && minutes > 0 && seconds == 0)
2257 txt += options.space + options.and + options.space;
2258 else if(hours > 0 && minutes > 0 && seconds > 0)
2259 txt += ',' + options.space;
2261 if(minutes > 1) txt += minutes.toString() + options.space + options.minutes;
2262 else if(minutes === 1) txt += minutes.toString() + options.space + options.minute;
2264 if((minutes > 0 || minutes > 0) && seconds > 0)
2265 txt += options.space + options.and + options.space;
2267 if(seconds > 1) txt += Math.floor(seconds).toString() + options.space + options.seconds;
2268 else if(seconds === 1) txt += Math.floor(seconds).toString() + options.space + options.second;
2270 return txt + suffix;
2273 function alarmsCallback(data) {
2275 for(x in data.alarms) {
2276 if(!data.alarms.hasOwnProperty(x)) continue;
2278 var alarm = data.alarms[x];
2279 if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL')
2284 document.getElementById('alarms_count_badge').innerHTML = count.toString();
2286 document.getElementById('alarms_count_badge').innerHTML = '';
2289 function initializeDynamicDashboardWithData(data) {
2291 options.hostname = data.hostname;
2292 options.data = data;
2293 options.version = data.version;
2294 netdataDashboard.os = data.os;
2296 if(typeof data.hosts != 'undefined')
2297 options.hosts = data.hosts;
2299 // update the dashboard hostname
2300 document.getElementById('hostname').innerHTML = options.hostname;
2301 document.getElementById('hostname').href = NETDATA.serverDefault;
2302 document.getElementById('netdataVersion').innerHTML = options.version;
2304 // update the dashboard title
2305 document.title = options.hostname + ' netdata dashboard';
2307 // close the splash screen
2308 $("#loadOverlay").css("display","none");
2310 // create a chart_by_name index
2311 data.charts_by_name = {};
2312 var charts = data.charts;
2315 if(!charts.hasOwnProperty(x)) continue;
2317 var chart = charts[x];
2318 data.charts_by_name[chart.name] = chart;
2321 // render all charts
2322 renderChartsAndMenu(data);
2326 function initializeDynamicDashboard(netdata_url) {
2327 if(typeof netdata_url === 'undefined' || netdata_url === null)
2328 netdata_url = NETDATA.serverDefault;
2330 // initialize clickable alarms
2331 NETDATA.alarms.chart_div_offset = 100;
2332 NETDATA.alarms.chart_div_id_prefix = 'chart_';
2333 NETDATA.alarms.chart_div_animation_duration = 0;
2335 NETDATA.pause(function() {
2336 NETDATA.alarms.callback = alarmsCallback;
2338 // download all the charts the server knows
2339 NETDATA.chartRegistry.downloadAll(netdata_url, function(data) {
2341 if(typeof data.custom_info !== 'undefined' && data.custom_info !== "") {
2342 loadJs(data.custom_info, function () {
2343 $.extend(true, netdataDashboard, customDashboard);
2344 initializeDynamicDashboardWithData(data);
2348 initializeDynamicDashboardWithData(data);
2355 // ----------------------------------------------------------------------------
2357 function versionLog(msg) {
2358 document.getElementById('versionCheckLog').innerHTML = msg;
2361 function getNetdataCommitIdFromVersion() {
2362 var s = options.version.split('-');
2364 if(s.length !== 3) return null;
2365 if(s[2][0] == 'g') {
2366 var v = s[2].split('_')[0].substring(1, 8);
2367 if(v.length === 7) {
2368 versionLog('Installed git commit id of netdata is ' + v);
2369 document.getElementById('netdataCommitId').innerHTML = v;
2376 function getNetdataCommitId(force, callback) {
2377 versionLog('Downloading installed git commit id from netdata...');
2383 xhrFields: { withCredentials: true } // required for the cookie
2385 .done(function(data) {
2386 data = data.replace(/(\r\n|\n|\r| |\t)/gm,"");
2388 var c = getNetdataCommitIdFromVersion();
2389 if(c !== null && data.length === 40 && data.substring(0, 7) !== c) {
2390 versionLog('Installed files commit id and internal netdata git commit id do not match');
2394 if(data.length >= 7) {
2395 versionLog('Installed git commit id of netdata is ' + data);
2396 document.getElementById('netdataCommitId').innerHTML = data.substring(0, 7);
2401 versionLog('Failed to download installed git commit id from netdata!');
2403 if(force === true) {
2404 var c = getNetdataCommitIdFromVersion();
2405 if(c === null) versionLog('Cannot find the git commit id of netdata.');
2413 function getGithubLatestCommit(callback) {
2414 versionLog('Downloading latest git commit id info from github...');
2417 url: 'https://api.github.com/repos/firehol/netdata/commits',
2421 .done(function(data) {
2422 versionLog('Latest git commit id from github is ' + data[0].sha);
2423 callback(data[0].sha);
2426 versionLog('Failed to download installed git commit id from github!');
2431 function checkForUpdate(force, callback) {
2432 getNetdataCommitId(force, function(sha1) {
2433 if(sha1 === null) callback(null, null);
2435 getGithubLatestCommit(function(sha2) {
2436 callback(sha1, sha2);
2443 function notifyForUpdate(force) {
2444 versionLog('<p>checking for updates...</p>');
2446 var now = Date.now();
2448 if(typeof force === 'undefined' || force !== true) {
2449 var last = loadLocalStorage('last_update_check');
2451 if(typeof last === 'string')
2452 last = parseInt(last);
2456 if(now - last < 3600000 * 8) {
2457 // no need to check it - too soon
2462 checkForUpdate(force, function(sha1, sha2) {
2467 versionLog('<p><big>Failed to get your netdata git commit id!</big></p><p>You can always get the latest netdata from <a href="https://github.com/firehol/netdata" target="_blank">its github page</a>.</p>');
2469 else if(sha2 === null) {
2471 versionLog('<p><big>Failed to get the latest git commit id from github.</big></p><p>You can always get the latest netdata from <a href="https://github.com/firehol/netdata" target="_blank">its github page</a>.</p>');
2473 else if(sha1 === sha2) {
2475 versionLog('<p><big>You already have the latest netdata!</big></p><p>No update yet?<br/>Probably, we need some motivation to keep going on!</p><p>If you haven\'t already, <a href="https://github.com/firehol/netdata" target="_blank">give netdata a <b>Star</b> at its github page</a>.</p>');
2479 var compare = 'https://github.com/firehol/netdata/compare/' + sha1.toString() + '...' + sha2.toString();
2481 versionLog('<p><big><strong>New version of netdata available!</strong></big></p><p>Latest commit: <b><code>' + sha2.substring(0, 7).toString() + '</code></b></p><p><a href="' + compare + '" target="_blank">Click here for the changes log</a> since your installed version, and<br/><a href="https://github.com/firehol/netdata/wiki/Updating-Netdata" target="_blank">click here for directions on updating</a> your netdata installation.</p><p>We suggest to review the changes log for new features you may be interested, or important bug fixes you may need.<br/>Keeping your netdata updated, is generally a good idea.</p>');
2483 document.getElementById('update_badge').innerHTML = '!';
2487 saveLocalStorage('last_update_check', now.toString());
2491 // ----------------------------------------------------------------------------
2493 function finalizePage() {
2494 // resize all charts - without starting the background thread
2495 // this has to be done while NETDATA is paused
2496 // if we ommit this, the affix menu will be wrong, since all
2497 // the Dom elements are initially zero-sized
2500 if(urlOptions.pan_and_zoom === true)
2501 NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before);
2503 // ------------------------------------------------------------------------
2504 // https://github.com/viralpatel/jquery.shorten/blob/master/src/jquery.shorten.js
2505 $.fn.shorten = function(settings) {
2511 ellipsesText: "...",
2512 moreText: '<i class="fa fa-expand" aria-hidden="true"></i> show more information',
2513 lessText: '<i class="fa fa-compress" aria-hidden="true"></i> show less information',
2514 onLess: function() { NETDATA.onscroll(); },
2515 onMore: function() { NETDATA.onscroll(); },
2521 $.extend(config, settings);
2524 if ($(this).data('jquery.shorten') && !config.force) {
2527 $(this).data('jquery.shorten', true);
2529 $(document).off("click", '.morelink');
2534 var $this = $(this);
2535 if ($this.hasClass('less')) {
2536 $this.removeClass('less');
2537 $this.html(config.moreText);
2538 $this.parent().prev().animate({'height':'0'+'%'}, 0, function () { $this.parent().prev().prev().show(); }).hide(0, function() {
2543 $this.addClass('less');
2544 $this.html(config.lessText);
2545 $this.parent().prev().animate({'height':'100'+'%'}, 0, function () { $this.parent().prev().prev().hide(); }).show(0, function() {
2553 return this.each(function() {
2554 var $this = $(this);
2556 var content = $this.html();
2557 var contentlen = $this.text().length;
2558 if (contentlen > config.showChars + config.minHideChars) {
2559 var c = content.substr(0, config.showChars);
2560 if (c.indexOf('<') >= 0) // If there's HTML don't want to cut it
2562 var inTag = false; // I'm in a tag?
2563 var bag = ''; // Put the characters to be shown here
2564 var countChars = 0; // Current bag size
2565 var openTags = []; // Stack for opened tags, so I can close them later
2568 for (var i = 0, r = 0; r <= config.showChars; i++) {
2569 if (content[i] == '<' && !inTag) {
2572 // This could be "tag" or "/tag"
2573 tagName = content.substring(i + 1, content.indexOf('>', i));
2575 // If its a closing tag
2576 if (tagName[0] == '/') {
2579 if (tagName != '/' + openTags[0]) {
2580 config.errMsg = 'ERROR en HTML: the top of the stack should be the tag that closes';
2582 openTags.shift(); // Pops the last tag from the open tag stack (the tag is closed in the retult HTML!)
2586 // There are some nasty tags that don't have a close tag like <br/>
2587 if (tagName.toLowerCase() != 'br') {
2588 openTags.unshift(tagName); // Add to start the name of the tag that opens
2592 if (inTag && content[i] == '>') {
2596 if (inTag) { bag += content.charAt(i); } // Add tag name chars to the result
2599 if (countChars <= config.showChars) {
2600 bag += content.charAt(i); // Fix to ie 7 not allowing you to reference string characters using the []
2602 } else // Now I have the characters needed
2604 if (openTags.length > 0) // I have unclosed tags
2606 //console.log('They were open tags');
2607 //console.log(openTags);
2608 for (var j = 0; j < openTags.length; j++) {
2609 //console.log('Cierro tag ' + openTags[j]);
2610 bag += '</' + openTags[j] + '>'; // Close all tags that were opened
2612 // 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
2619 c = $('<div/>').html(bag + '<span class="ellip">' + config.ellipsesText + '</span>').html();
2621 c+=config.ellipsesText;
2624 var html = '<div class="shortcontent">' + c +
2625 '</div><div class="allcontent">' + content +
2626 '</div><span><a href="javascript://nop/" class="morelink">' + config.moreText + '</a></span>';
2629 $this.find(".allcontent").hide(); // Hide all text
2630 $('.shortcontent p:last', $this).css('margin-bottom', 0); //Remove bottom margin on last paragraph as it's likely shortened
2635 $(".chart-message").shorten();
2636 // ------------------------------------------------------------------------
2638 // callback for us to track PanAndZoom operations
2639 NETDATA.globalPanAndZoom.callback = urlOptions.netdataPanAndZoomCallback;
2641 // let it run (update the charts)
2644 // check if we have to jump to a specific section
2645 scrollToId(urlOptions.hash.replace('#',''));
2647 if(urlOptions.chart !== null) {
2648 NETDATA.alarms.scrollToChart(urlOptions.chart);
2649 //urlOptions.hash = '#' + NETDATA.name2id('menu_' + charts[c].menu + '_submenu_' + charts[c].submenu);
2650 //urlOptions.hash = '#chart_' + NETDATA.name2id(urlOptions.chart);
2651 //console.log('hash = ' + urlOptions.hash);
2654 var $sidebar = $('#sidebar');
2655 /* activate bootstrap sidebar (affix) */
2658 top: (isdemo())?150:0,
2663 /* fix scrolling of very long affix lists
2664 http://stackoverflow.com/questions/21691585/bootstrap-3-1-0-affix-too-long
2666 $sidebar.on('affixed.bs.affix', function() {
2667 $(this).removeAttr('style');
2670 /* activate bootstrap scrollspy (needed for sidebar) */
2671 $(document.body).scrollspy({
2673 offset: $(window).height() / 5 // controls the diff of the <hX> element to the top, to select it
2676 // change the URL based on the current position of the screen
2677 $sidebar.on('activate.bs.scrollspy', function (e) {
2679 var el = $(e.target);
2680 //if(el.find('ul').size() == 0) {
2681 var hash = el.find('a').attr('href');
2682 if(typeof hash === 'string' && hash.substring(0, 1) === '#' && urlOptions.hash.startsWith(hash + '_submenu_') === false) {
2683 urlOptions.hash = hash;
2684 //console.log(urlOptions.hash);
2685 urlOptions.hashUpdate();
2687 //else console.log('hash: not accepting ' + hash);
2689 //else console.log('el.find(): not found');
2692 document.getElementById('footer').style.display = 'block';
2694 var update_options_modal = function() {
2695 // console.log('update_options_modal');
2697 var sync_option = function(option) {
2698 var self = $('#' + option);
2700 if(self.prop('checked') !== NETDATA.getOption(option)) {
2701 // console.log('switching ' + option.toString());
2702 self.bootstrapToggle(NETDATA.getOption(option)?'on':'off');
2706 var theme_sync_option = function(option) {
2707 var self = $('#' + option);
2709 self.bootstrapToggle(netdataTheme === 'slate'?'on':'off');
2712 sync_option('eliminate_zero_dimensions');
2713 sync_option('destroy_on_hide');
2714 sync_option('async_on_scroll');
2715 sync_option('parallel_refresher');
2716 sync_option('concurrent_refreshes');
2717 sync_option('sync_selection');
2718 sync_option('sync_pan_and_zoom');
2719 sync_option('stop_updates_when_focus_is_lost');
2720 sync_option('smooth_plot');
2721 sync_option('pan_and_zoom_data_padding');
2722 sync_option('show_help');
2723 theme_sync_option('netdata_theme_control');
2725 if(NETDATA.getOption('parallel_refresher') === false) {
2726 $('#concurrent_refreshes_row').hide();
2729 $('#concurrent_refreshes_row').show();
2732 NETDATA.setOption('setOptionCallback', update_options_modal);
2734 // handle options changes
2735 $('#eliminate_zero_dimensions').change(function() { NETDATA.setOption('eliminate_zero_dimensions', $(this).prop('checked')); });
2736 $('#destroy_on_hide').change(function() { NETDATA.setOption('destroy_on_hide', $(this).prop('checked')); });
2737 $('#async_on_scroll').change(function() { NETDATA.setOption('async_on_scroll', $(this).prop('checked')); });
2738 $('#parallel_refresher').change(function() { NETDATA.setOption('parallel_refresher', $(this).prop('checked')); });
2739 $('#concurrent_refreshes').change(function() { NETDATA.setOption('concurrent_refreshes', $(this).prop('checked')); });
2740 $('#sync_selection').change(function() { NETDATA.setOption('sync_selection', $(this).prop('checked')); });
2741 $('#sync_pan_and_zoom').change(function() { NETDATA.setOption('sync_pan_and_zoom', $(this).prop('checked')); });
2742 $('#stop_updates_when_focus_is_lost').change(function() {
2743 urlOptions.update_always = !$(this).prop('checked');
2744 urlOptions.hashUpdate();
2746 NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always);
2748 $('#smooth_plot').change(function() { NETDATA.setOption('smooth_plot', $(this).prop('checked')); });
2749 $('#pan_and_zoom_data_padding').change(function() { NETDATA.setOption('pan_and_zoom_data_padding', $(this).prop('checked')); });
2750 $('#show_help').change(function() {
2751 urlOptions.help = $(this).prop('checked');
2752 urlOptions.hashUpdate();
2754 NETDATA.setOption('show_help', urlOptions.help);
2758 // this has to be the last
2759 // it reloads the page
2760 $('#netdata_theme_control').change(function() {
2761 urlOptions.theme = $(this).prop('checked')?'slate':'white';
2762 urlOptions.hashUpdate();
2764 if(setTheme(urlOptions.theme))
2768 var $updateModal = $('#updateModal');
2769 $updateModal.on('show.bs.modal', function() {
2770 versionLog('checking, please wait...');
2773 $updateModal.on('shown.bs.modal', function() {
2774 notifyForUpdate(true);
2777 var $alarmsModal = $('#alarmsModal');
2778 $alarmsModal.on('shown.bs.modal', function() {
2779 NETDATA.pause(alarmsUpdateModal);
2782 $alarmsModal.on('hidden.bs.modal', function() {
2784 document.getElementById('alarms_active').innerHTML =
2785 document.getElementById('alarms_all').innerHTML =
2786 document.getElementById('alarms_log').innerHTML =
2790 $('#deleteRegistryModal').on('hidden.bs.modal', function() {
2791 deleteRegistryGuid = null;
2795 // do not to give errors on netdata demo servers for 60 seconds
2796 NETDATA.options.current.retries_on_data_failures = 60;
2798 if(urlOptions.nowelcome !== true) {
2799 setTimeout(function() {
2800 $('#welcomeModal').modal();
2804 // google analytics when this is used for the home page of the demo sites
2805 // this does not run on user's installations
2806 setTimeout(function() {
2807 (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
2808 (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
2809 m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
2810 })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
2812 ga('create', 'UA-64295674-3', 'auto');
2813 ga('send', 'pageview');
2816 else notifyForUpdate();
2818 if(urlOptions.show_alarms === true)
2819 setTimeout(function() { $('#alarmsModal').modal('show'); }, 1000);
2821 var sidebar = document.getElementById('sidebar');
2822 Ps.initialize(sidebar, {
2824 wheelPropagation: true,
2825 swipePropagation: true,
2826 minScrollbarLength: null,
2827 maxScrollbarLength: null,
2828 useBothWheelAxes: false,
2829 suppressScrollX: true,
2830 suppressScrollY: false,
2831 scrollXMarginOffset: 0,
2832 scrollYMarginOffset: 0,
2837 var registry = document.getElementById('myNetdataDropdownUL');
2838 Ps.initialize(registry, {
2840 wheelPropagation: false,
2841 swipePropagation: false,
2842 minScrollbarLength: null,
2843 maxScrollbarLength: null,
2844 useBothWheelAxes: false,
2845 suppressScrollX: true,
2846 suppressScrollY: false,
2847 scrollXMarginOffset: 0,
2848 scrollYMarginOffset: 0,
2851 Ps.update(registry);
2853 NETDATA.onresizeCallback = function() {
2855 Ps.update(registry);
2858 $('#myNetdataDropdownParent')
2859 .on('show.bs.dropdown', function () {
2860 NETDATA.pause(function() {});
2862 .on('shown.bs.dropdown', function () {
2863 Ps.update(registry);
2865 .on('hidden.bs.dropdown', function () {
2869 // var netdataEnded = performance.now();
2870 // console.log('start up time: ' + (netdataEnded - netdataStarted).toString() + ' ms');
2873 function resetDashboardOptions() {
2874 var help = NETDATA.options.current.show_help;
2876 NETDATA.resetOptions();
2877 if(setTheme('slate'))
2880 if(help !== NETDATA.options.current.show_help)
2884 // callback to add the dashboard info to the
2885 // parallel javascript downloader in netdata
2886 var netdataPrepCallback = function() {
2887 NETDATA.requiredCSS.push({
2888 url: NETDATA.serverDefault + 'css/bootstrap-toggle-2.2.2.min.css',
2889 isAlreadyLoaded: function() { return false; }
2892 NETDATA.requiredJs.push({
2893 url: NETDATA.serverDefault + 'lib/bootstrap-toggle-2.2.2.min.js',
2894 isAlreadyLoaded: function() { return false; }
2897 NETDATA.requiredJs.push({
2898 url: NETDATA.serverDefault + 'dashboard_info.js?v20170325-1',
2900 isAlreadyLoaded: function() { return false; }
2904 document.getElementById('masthead').style.display = 'block';
2907 if(urlOptions.update_always === true)
2908 NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always);
2913 // var netdataStarted = performance.now();
2914 var netdataCallback = initializeDynamicDashboard;
2918 <body data-spy="scroll" data-target="#sidebar">
2919 <div id="loadOverlay" class="loadOverlay" style="background-color: #888; color: #888;">
2920 netdata<br/><div style="font-size: 3vh;">Real-time performance monitoring, done right!</div>
2922 <script type="text/javascript">
2923 // change the loadOverlay colors ASAP to match the theme
2924 document.getElementById('loadOverlay').style = (urlOptions.theme === 'slate')?"background-color:#272b30; color: #373b40;":"background-color:#fff; color: #ddd;";
2926 <nav class="navbar navbar-default navbar-fixed-top" role="banner">
2927 <div class="container">
2928 <nav id="mynetdata_nav" class="collapse navbar-collapse navbar-left hidden-sm hidden-xs" role="navigation" style="padding-right: 20px;">
2929 <ul class="nav navbar-nav">
2930 <li class="dropdown" id="myNetdataDropdownParent">
2931 <a href="#" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a>
2932 <ul class="dropdown-menu scrollable-menu inpagemenu multi-column columns-2" role="menu" id="myNetdataDropdownUL">
2934 <div class="col-sm-6" style="width: 85%; padding-right: 0;">
2935 <ul id="mynetdata_servers" class="multi-column-dropdown">
2936 <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li>
2939 <div class="col-sm-3 hidden-xs" style="width: 15%; padding-left: 0;">
2940 <ul id="mynetdata_actions1" class="multi-column-dropdown">
2941 <li style="color: #999;"> </li>
2949 <div class="navbar-header">
2950 <button class="navbar-toggle" type="button" data-toggle="collapse" data-target=".navbar-collapse">
2951 <span class="sr-only">Toggle navigation</span>
2952 <span class="icon-bar"></span>
2953 <span class="icon-bar"></span>
2954 <span class="icon-bar"></span>
2956 <a href="/" class="navbar-brand" id="hostname" title="reload the dashboard">netdata</a>
2958 <nav class="collapse navbar-collapse navbar-right" role="navigation">
2959 <ul class="nav navbar-nav">
2960 <li><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal" title="alarms"><i class="fa fa-bell"></i> <span class="hidden-sm">Alarms </span><span id="alarms_count_badge" class="badge"></span></a></li>
2961 <li><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal" title="dashboard settings"><i class="fa fa-sliders"></i> <span class="hidden-sm">Settings</span></a></li>
2962 <li class="hidden-sm" id="updateButton"><a href="#" class="btn" data-toggle="modal" data-target="#updateModal" title="check for update"><i class="fa fa-cloud-download"></i> <span class="hidden-sm hidden-md">Update </span><span id="update_badge" class="badge"></span></a></li>
2963 <li><a href="https://github.com/firehol/netdata/wiki" class="btn" target="_blank" title="netdata on github"><i class="fa fa-github"></i></a></li>
2964 <li><a href="https://twitter.com/linuxnetdata" class="btn" target="_blank" title="netdata on twitter"><i class="fa fa-twitter" aria-hidden="true"></i></a></li>
2965 <li><a href="https://www.facebook.com/linuxnetdata/" class="btn" target="_blank" title="netdata on facebook"><i class="fa fa-facebook-official" aria-hidden="true"></i></a></li>
2966 <li class="hidden-sm"><a href="#" class="btn" data-toggle="modal" data-target="#helpModal" title="dashboard help"><i class="fa fa-question-circle"></i> <span class="hidden-sm hidden-md">Help</span></a></li>
2967 <li class="dropdown hidden-sm hidden-md hidden-lg">
2968 <a href="#" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a>
2969 <ul id="mynetdata_servers2" class="dropdown-menu scrollable-menu inpagemenu" role="menu">
2970 <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li>
2978 <div id="masthead" style="display: none;">
2979 <div class="container">
2981 <div class="col-md-7">
2983 <p class="lead">Real-time performance monitoring, in the greatest possible detail</p>
2986 <div class="col-md-5">
2987 <div class="well well-lg">
2989 <div class="col-md-6">
2990 <b>Drag</b> charts to pan.
2991 <b>Shift + wheel</b> on them, to zoom in and out.
2992 <b>Double-click</b> on them, to reset.
2993 <b>Hover</b> on them too!
2995 <div class="col-md-6">
2996 <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>
3005 <div class="container">
3007 <div class="charts-body" role="main">
3008 <div id="charts_div"></div>
3010 <div class="sidebar-body hidden-xs hidden-sm" id="sidebar-body" role="complementary">
3011 <nav class="dashboard-sidebar hidden-print hidden-xs hidden-sm" id="sidebar" role="menu"></nav>
3016 <div id="footer" class="container" style="display: none;">
3018 <div class="col-md-10" role="main">
3020 <big><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></big><br/>
3021 <i class="fa fa-copyright"></i> Copyright 2016-2017, <a href="mailto:costa@tsaousis.gr">Costa Tsaousis</a>.<br/>
3022 Released under <a href="http://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">GPL v3 or later</a>.<br/>
3026 <a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a> re-distributes these software tools:
3028 <i class="fa fa-circle"></i> The excellent <a href="http://dygraphs.com/" target="_blank">Dygraphs.com</a> web chart library,
3029 <i class="fa fa-copyright"></i> Copyright 2009, Dan Vanderkam, <a href="http://dygraphs.com/legal.html" target="_blank">MIT License</a>
3031 <i class="fa fa-circle"></i> <a href="https://rendro.github.io/easy-pie-chart/" target="_blank">Easy Pie Chart</a> web chart library,
3032 <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>
3034 <i class="fa fa-circle"></i> <a href="http://bernii.github.io/gauge.js/" target="_blank">Gauge.js</a> web chart library,
3035 <i class="fa fa-copyright"></i> Copyright, Bernard Kobos, <a href="http://bernii.github.io/gauge.js/" target="_blank">MIT License</a>
3037 <i class="fa fa-circle"></i> <a href="https://jquery.org/" target="_blank">jQuery</a>,
3038 <i class="fa fa-copyright"></i> Copyright 2015, jQuery Foundation, <a href="https://jquery.org/license/" target="_blank">MIT License</a>
3040 <i class="fa fa-circle"></i> <a href="http://getbootstrap.com/getting-started/" target="_blank">Bootstrap</a>,
3041 <i class="fa fa-copyright"></i> Copyright 2015, Twitter, <a href="http://getbootstrap.com/getting-started/#license-faqs" target="_blank">MIT License</a>
3043 <i class="fa fa-circle"></i> <a href="http://www.bootstraptoggle.com/" target="_blank">Bootstrap Toggle</a>,
3044 <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>
3046 <i class="fa fa-circle"></i> <a href="https://github.com/noraesae/perfect-scrollbar" target="_blank">perfect-scrollbar</a>,
3047 <i class="fa fa-copyright"></i> Copyright 2016, Hyunje Alex Jun and other contributors, <a href="https://github.com/noraesae/perfect-scrollbar/blob/master/LICENSE" target="_blank">MIT License</a>
3049 <i class="fa fa-circle"></i> <a href="https://fortawesome.github.io/Font-Awesome/" target="_blank">FontAwesome</a>,
3050 <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>
3052 <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.
3054 <i class="fa fa-circle"></i> <a href="http://bootstrap-table.wenzhixin.net.cn/" target="_blank">bootstrap-table</a>,
3055 <i class="fa fa-copyright"></i> Copyright (c) 2012-2016 Zhixin Wen, <a href="https://github.com/wenzhixin/bootstrap-table/blob/master/LICENSE" target="_blank">MIT License</a>
3057 <i class="fa fa-circle"></i> <a href="https://github.com/hhurz/tableExport.jquery.plugin" target="_blank">tableExport.jquery.plugin</a>,
3058 <i class="fa fa-copyright"></i> Copyright (c) 2015,2016 hhurz, <a href="http://rawgit.com/hhurz/tableExport.jquery.plugin/master/tableExport.js" target="_blank">MIT License</a>
3066 <div class="modal fade" id="welcomeModal" tabindex="-1" role="dialog" aria-labelledby="welcomeModalLabel">
3067 <div class="modal-dialog modal-lg" role="document">
3068 <div class="modal-content">
3069 <div class="modal-header">
3070 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
3071 <h4 class="modal-title" id="welcomeModalLabel">Welcome to the world of netdata</h4>
3073 <div class="modal-body">
3075 <div style="width: 100%; text-align: center; padding-top: 10px; padding-bottom: 10px; font-size: 18px;">
3076 if there is a metric for something, we want it visualised<br/>
3077 and we want this visualisation to be <strong>real-time</strong>, <strong>efficient</strong> and <strong>awesome</strong>
3081 <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>
3082 is a new way to monitor your systems and applications, to get <strong>real-time insights</strong>
3083 of what is really happening and what affects performance.
3084 It is carefully optimised to be a real-time system, without interfering in any way,
3085 to the core function of your systems.
3088 <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>
3089 has been designed to monitor <strong>massive amounts of metrics, per server, per second</strong>.
3090 When installed, it might come up with 1k to 3k metrics, but we have been testing it with 100k
3091 metrics, all collected per second, and still the cpu utilisation remained negligible.
3093 We have also tried to give each metric, a meaning, a context.
3094 We have grouped and categorized all metrics into meaningful charts, providing a
3095 better understanding of the underlying technologies and mechanisms.
3098 <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> is free,
3099 open-source software. If you decide to use it,
3100 <strong><a href="https://github.com/firehol/netdata/wiki/a-github-star-is-important" target="_blank">it is important to give netdata a star at GitHub</a></strong>.
3103 Enjoy real-time performance monitoring!
3109 <div class="modal-footer">
3110 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3116 <div class="modal fade" id="helpModal" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel">
3117 <div class="modal-dialog modal-lg" role="document">
3118 <div class="modal-content">
3119 <div class="modal-header">
3120 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
3121 <h4 class="modal-title" id="helpModalLabel">Dashboard Help</h4>
3123 <div class="modal-body">
3125 <h4>Dygraphs (line, area and stacked area charts)</h4>
3128 <ul class="nav nav-tabs" role="tablist">
3129 <li role="presentation" class="active"><a href="#help_mouse" aria-controls="help_mouse" role="tab" data-toggle="tab">Mouse Interface</a></li>
3130 <li role="presentation"><a href="#help_touch" aria-controls="help_touch" role="tab" data-toggle="tab">Touch Interface</a></li>
3134 <div class="tab-content">
3135 <div role="tabpanel" class="tab-pane active" id="help_mouse">
3137 <h4>Mouse Over / Hover</h4>
3138 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).
3140 All the other visible charts will also show and highlight their values for the same timestamp.
3144 <h4>Drag Chart Contents</h4>
3145 Drag the contents of a chart to pan it horizontally.
3147 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).
3149 Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double click</b> a panned chart.
3153 <h4>Double Click</h4>
3154 Double Click a chart to reset all the charts to their default auto-refreshing state.
3158 <h4>SHIFT + Drag</h4>
3159 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:
3161 <li>The already loaded chart contents are zoomed (low resolution)</li>
3162 <li>New data are transferred from the netdata server, to refresh the chart with possibly more detail.</li>
3164 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
3168 <h4>SHIFT + Mouse Wheel</h4>
3169 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.
3171 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
3175 <h4>Legend Operations</h4>
3176 Click on the label or value of a dimension, will select / un-select this dimension.
3178 You can press any of the SHIFT or CONTROL keys and then click on legend labels or values, to select / un-select multiple dimensions.
3181 <div role="tabpanel" class="tab-pane" id="help_touch">
3184 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).
3186 All the other visible charts will also show and highlight their values for the same timestamp.
3190 <h4>Drag Chart Contents</h4>
3191 Touch and Drag the contents of a chart to pan it horizontally.
3193 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).
3195 Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double tap</b> a panned chart.
3200 Double tap a chart to reset all the charts to their default auto-refreshing state.
3204 <h4>Zoom <small>(does not work on firefox and IE/Edge)</small></h4>
3205 With two fingers, zoom in or out.
3207 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
3211 <h4>Legend Operations</h4>
3212 Tap on the label or value of a dimension, will select / un-select this dimension.
3217 <div class="modal-footer">
3218 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3224 <div class="modal fade" id="alarmsModal" tabindex="-1" role="dialog" aria-labelledby="alarmsModalLabel">
3225 <div class="modal-dialog modal-lg" role="document" style="display: table;"> <!-- allow the modal to expand horizontally -->
3226 <div class="modal-content">
3227 <div class="modal-header">
3228 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
3229 <h4 class="modal-title" id="alarmsModalLabel">netdata alarms</h4>
3231 <div class="modal-body">
3233 <ul class="nav nav-tabs" role="tablist">
3234 <li role="presentation" class="active"><a href="#alarms_active" aria-controls="alarms_active" role="tab" data-toggle="tab">Active</a></li>
3235 <li role="presentation"><a href="#alarms_all" aria-controls="alarms_all" role="tab" data-toggle="tab">All</a></li>
3236 <li role="presentation"><a href="#alarms_log" aria-controls="alarms_log" role="tab" data-toggle="tab">Log</a></li>
3240 <div class="tab-content">
3241 <div role="tabpanel" class="tab-pane active" id="alarms_active">
3244 <div role="tabpanel" class="tab-pane" id="alarms_all">
3247 <div role="tabpanel" class="tab-pane" id="alarms_log">
3252 <div class="modal-footer">
3253 <!-- <a href="#" onclick="alarmsUpdateModal(); return false;" type="button" class="btn btn-default">Update</a> -->
3254 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3260 <div class="modal fade" id="optionsModal" tabindex="-1" role="dialog" aria-labelledby="optionsModalLabel">
3261 <div class="modal-dialog modal-lg" role="document">
3262 <div class="modal-content">
3263 <div class="modal-header">
3264 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
3265 <h4 class="modal-title" id="optionsModalLabel">netdata dashboard options</h4>
3267 <div class="modal-body">
3269 <small style="color: #BBBBBB;">These are browser settings. Each viewer has its own. They do not affect the operation of your netdata server.
3271 Settings take effect immediately and are saved permanently to browser local storage (except the refresh on focus / always option).
3273 To reset all options (including charts sizes) to their defaults, click <a href="#" onclick="resetDashboardOptions(); return false;">here</a>.</small>
3275 <div style="padding: 10px;"></div>
3278 <ul class="nav nav-tabs" role="tablist">
3279 <li role="presentation" class="active"><a href="#settings_performance" aria-controls="settings_performance" role="tab" data-toggle="tab">Performance</a></li>
3280 <li role="presentation"><a href="#settings_sync" aria-controls="settings_sync" role="tab" data-toggle="tab">Synchronization</a></li>
3281 <li role="presentation"><a href="#settings_visual" aria-controls="settings_visual" role="tab" data-toggle="tab">Visual</a></li>
3285 <div class="tab-content">
3286 <div role="tabpanel" class="tab-pane active" id="settings_performance">
3287 <form id="optionsForm1" method="get" class="form-horizontal">
3288 <div class="form-group">
3290 <tr class="option-row">
3291 <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>
3292 <td class="option-info"><strong>When to refresh the charts?</strong><br/>
3293 <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>
3296 <tr class="option-row">
3297 <td class="option-control">
3298 <input id="eliminate_zero_dimensions" type="checkbox" checked data-toggle="toggle" data-on="Non Zero" data-off="All" data-width="110px">
3300 <td class="option-info"><strong>Which dimensions to show?</strong><br/>
3301 <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>
3304 <tr class="option-row">
3305 <td class="option-control"><input id="destroy_on_hide" type="checkbox" data-toggle="toggle" data-on="Destroy" data-off="Hide" data-width="110px"></td>
3306 <td class="option-info"><strong>How to handle hidden charts?</strong><br/>
3307 <small>When set to <b>Destroy</b>, charts that are not in the current viewport of the browser (are above, or below the visible area of the page), will be destroyed and re-created if and when they become visible again. When set to <b>Hide</b>, the not-visible charts will be just hidden, to simplify the DOM and speed up your browser. Set it to <b>Destroy</b>, to lower the memory requirements of your browser. Set it to <b>Hide</b> for faster restoration of charts on page scrolling.</small>
3310 <tr class="option-row">
3311 <td class="option-control"><input id="async_on_scroll" type="checkbox" data-toggle="toggle" data-on="Async" data-off="Sync" data-width="110px"></td>
3312 <td class="option-info"><strong>Page scroll handling?</strong><br/>
3313 <small>When set to <b>Sync</b>, charts will be examined for their visibility synchronously. On slow computers this may impact the smoothness of page scrolling. To work asynchronously set it to <b>Async</b>. When set to <b>Sync</b>, the performance of page scrolling is monitored and this setting switches automatically to <b>Async</b> if the browser is found slow. Set it to <b>Sync</b> for best visual experience. Set it to <b>Async</b> for smoother page scrolling.</small>
3320 <div role="tabpanel" class="tab-pane" id="settings_sync">
3321 <form id="optionsForm2" method="get" class="form-horizontal">
3322 <div class="form-group">
3324 <tr class="option-row">
3325 <td class="option-control"><input id="parallel_refresher" type="checkbox" checked data-toggle="toggle" data-on="Parallel" data-off="Sequential" data-width="110px"></td>
3326 <td class="option-info"><strong>Which chart refresh policy to use?</strong><br/>
3327 <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>
3330 <tr class="option-row" id="concurrent_refreshes_row">
3331 <td class="option-control"><input id="concurrent_refreshes" type="checkbox" checked data-toggle="toggle" data-on="Resync" data-off="Best Effort" data-width="110px"></td>
3332 <td class="option-info"><strong>Shall we re-sync chart refreshes?</strong><br/>
3333 <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>
3336 <tr class="option-row">
3337 <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>
3338 <td class="option-info"><strong>Sync hover selection on all charts?</strong><br/>
3339 <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>
3342 <tr class="option-row">
3343 <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>
3344 <td class="option-info"><strong>Sync pan and zoom on all charts?</strong><br/>
3345 <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>
3352 <div role="tabpanel" class="tab-pane" id="settings_visual">
3353 <form id="optionsForm3" method="get" class="form-horizontal">
3354 <div class="form-group">
3356 <tr class="option-row">
3357 <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>
3358 <td class="option-info"><strong>Which theme to use?</strong><br/>
3359 <small>Netdata comes with two themes: <b>Dark</b> (the default) and <b>White</b>.
3361 <b>Switching this will reload the dashboard</b>.
3365 <tr class="option-row">
3366 <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>
3367 <td class="option-info"><strong>Do you need help?</strong><br/>
3368 <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.
3370 <b>Switching this will reload the dashboard</b>.
3374 <tr class="option-row">
3375 <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>
3376 <td class="option-info"><strong>Enable data padding when panning and zooming?</strong><br/>
3377 <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>
3380 <tr class="option-row">
3381 <td class="option-control"><input id="smooth_plot" type="checkbox" checked data-toggle="toggle" data-on="Smooth" data-off="Rough" data-width="110px"></td>
3382 <td class="option-info"><strong>Enable Bézier lines on charts?</strong><br/>
3383 <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.
3385 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>
3394 <div class="modal-footer">
3395 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3402 <div class="modal fade" id="updateModal" tabindex="-1" role="dialog" aria-labelledby="updateModalLabel">
3403 <div class="modal-dialog" role="document">
3404 <div class="modal-content">
3405 <div class="modal-header">
3406 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
3407 <h4 class="modal-title" id="updateModalLabel">Update Check</h4>
3409 <div class="modal-body">
3410 Your netdata version: <b><code><span id="netdataVersion">Unknown</span></code></b><br/>
3411 Your netdata commit: <b><code><span id="netdataCommitId">Unknown</span></code></b>
3413 <div style="padding: 10px;"></div>
3414 <div id="versionCheckLog">Not checked yet. Please press the Check Now button.</div>
3419 For progress reports and key netdata updates: <strong><a href="https://twitter.com/linuxnetdata" target="_blank">follow netdata on <i class="fa fa-twitter" aria-hidden="true"></i> twitter</a></strong>.
3422 You can also <a href="https://www.facebook.com/linuxnetdata/" target="_blank">follow netdata on <i class="fa fa-facebook" aria-hidden="true"></i> facebook</a>,
3423 or <a href="https://github.com/firehol/netdata" target="_blank">watch netdata on <i class="fa fa-github" aria-hidden="true"></i> github</a>.
3427 <div class="modal-footer">
3428 <a href="#" onclick="notifyForUpdate(true); return false;" type="button" class="btn btn-default">Check Now</a>
3429 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3435 <div class="modal fade" id="deleteRegistryModal" tabindex="-1" role="dialog" aria-labelledby="deleteRegistryModalLabel">
3436 <div class="modal-dialog" role="document">
3437 <div class="modal-content">
3438 <div class="modal-header">
3439 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
3440 <h4 class="modal-title" id="deleteRegistryModalLabel">Delete <span id="deleteRegistryServerName"></span>?</h4>
3442 <div class="modal-body">
3443 You are about to delete, from your personal list of netdata servers, the following server:
3444 <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;">
3445 <b><span id="deleteRegistryServerName2"></span></b>
3447 <b><span id="deleteRegistryServerURL"></span></b>
3449 Are you sure you want to do this?
3451 <div style="padding: 10px;"></div>
3452 <small>Keep in mind, this server will be added back if and when you visit it again.</small>
3454 <div id="deleteRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
3456 <div class="modal-footer">
3457 <button type="button" class="btn btn-success" data-dismiss="modal">keep it</button>
3458 <a href="#" onclick="notifyForDeleteRegistry(true); return false;" type="button" class="btn btn-danger">delete it</a>
3464 <div class="modal fade" id="switchRegistryModal" tabindex="-1" role="dialog" aria-labelledby="switchRegistryModalLabel">
3465 <div class="modal-dialog" role="document">
3466 <div class="modal-content">
3467 <div class="modal-header">
3468 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
3469 <h4 class="modal-title" id="switchRegistryModalLabel">Switch Netdata Registry Identity</h4>
3471 <div class="modal-body">
3472 You can copy and paste the following ID to all your browsers (e.g. work and home).
3474 All the browsers with the same ID will identify <b>you</b>, so please don't share this with others.
3475 <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;">
3477 <input type="text" class="form-control" id="switchRegistryPersonGUID" placeholder="your personal ID" maxlength="36" autocomplete="off" style="text-align: center; font-size: 1.4em;">
3480 Either copy this ID and paste it to another browser, or paste here the ID you have taken from another browser.
3481 <p style="padding-top: 10px;"><small>
3484 <li>when you switch ID, your previous ID will be lost forever - this is irreversible.</li>
3485 <li>both IDs (your old and the new) must list this netdata at their personal lists.</li>
3486 <li>both IDs have to be known by the registry: <b><span id="switchRegistryURL"></span></b>.</li>
3487 <li>to get a new ID, just clear your browser cookies.</li>
3490 <div id="switchRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
3492 <div class="modal-footer">
3493 <button type="button" class="btn btn-success" data-dismiss="modal">cancel</button>
3494 <a href="#" onclick="notifyForSwitchRegistry(true); return false;" type="button" class="btn btn-danger">impersonate</a>
3500 <div class="modal fade" id="gotoServerModal" tabindex="-1" role="dialog" aria-labelledby="gotoServerModalLabel">
3501 <div class="modal-dialog" role="document">
3502 <div class="modal-content">
3503 <div class="modal-header">
3504 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
3505 <h4 class="modal-title" id="gotoServerModalLabel"><span id="gotoServerName"></span></h4>
3507 <div class="modal-body">
3508 Checking known URLs for this server...
3509 <div style="padding-top: 20px;">
3510 <table id="gotoServerList">
3513 <p style="padding-top: 10px;"><small>
3514 Checks may fail if you are viewing an HTTPS page and the server to be checked is HTTP only.
3516 <div id="gotoServerResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
3518 <div class="modal-footer">
3519 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3526 <script type="text/javascript" src="dashboard.js?v20170325-1"></script>