<!DOCTYPE html> <html lang="en"> <head> <title>netdata dashboard</title> <meta name="application-name" content="netdata"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <meta name="author" content="costa@tsaousis.gr"> <!-- <link rel="shortcut icon" href="images/seo-performance-multi-size.ico"> --> <!-- <link rel="apple-touch-icon" href="images/seo-performance-72.png"> --> <!-- <link rel="apple-touch-icon" sizes="72x72" href="images/seo-performance-72.png"> --> <!-- <link rel="apple-touch-icon" sizes="114x114" href="images/seo-performance-114.png"> --> <!-- <link rel="icon" type="image/png" sizes="512x512" href="images/seo-performance-512.png"> --> <!-- <link rel="icon" type="image/png" sizes="256x256" href="images/seo-performance-256.png"> --> <!-- <link rel="icon" type="image/png" sizes="128x128" href="images/seo-performance-128.png"> --> <!-- <link rel="icon" type="image/png" sizes="64x64" href="images/seo-performance-64.png"> --> <!-- <link rel="icon" type="image/png" sizes="48x48" href="images/seo-performance-48.png"> --> <!-- <link rel="icon" type="image/png" sizes="24x24" href="images/seo-performance-24.png"> --> <!-- <link rel="icon" type="image/png" sizes="16x16" href="images/seo-performance-16.png"> --> <!-- <link rel="icon" type="image/png" sizes="32x32" href="images/seo-performance-32.png"> --> <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="> <meta property="og:locale" content="en_US" /> <meta property="og:image" content="http://my-netdata.io/images/post.png"/> <meta property="og:url" content="http://my-netdata.io/"/> <meta property="og:type" content="website"/> <meta property="og:site_name" content="netdata"/> <meta property="og:title" content="netdata - real-time performance monitoring, done right!"/> <meta property="og:description" content="Stunning real-time dashboards, blazingly fast and extremely interactive. Zero configuration, zero dependencies, zero maintenance." /> <style> /* prevent body from hiding under the navbar */ body { padding-top: 50px; } .loadOverlay { position: absolute; top: 0px; left: 0px; width: 100%; height:100%; z-index: 2000; font-size: 10vh; font-family: sans-serif; padding: 40vh 0 40vh 0; font-weight: bold; text-align: center; } .modal-wide .modal-dialog { width: 80%; } /* fix # anchors scrolling under the navbar https://github.com/twbs/bootstrap/issues/1768#issuecomment-46519033 */ h1 { position: relative; z-index: -1; } h2 { position: relative; z-index: -2; } h1:before, h2:before { display: block; content: " "; margin-top: -70px; height: 70px; visibility: hidden; } .p { display: block; margin-top: 15px; } .option-row, .option-control { vertical-align: top; padding: 10px; padding-top: 30px; padding-left: 30px; } .option-info { padding: 10px; } .chart-message { display: block; margin-top: 10px; } #masthead h1 { /*font-size: 30px;*/ line-height: 1; padding-top: 30px; } #masthead .well { margin-top:4%; } /* fix the navbar shifting when a modal is open */ /* https://github.com/twbs/bootstrap/issues/14040#issuecomment-159891033 */ body.modal-open{ width: 100% !important; padding-right: 0 !important; /* overflow-y: scroll !important; */ /* position: fixed !important;*/ overflow: visible; } /* make accordion use the whole header bar for expand/collapse */ .panel-title a { display: block; padding: 10px 15px; margin: -10px -15px; } /* * Side navigation * * Scrollspy and affixed enhanced navigation to highlight sections and secondary * sections of docs content. */ .affix { position: static; top: 70px !important; /*width: 220px;*/ } .affix-top { /*width: 220px;*/ } .dashboard-sidebar { max-height: calc(100% - 70px) !important; overflow-y: auto; /*width: 220px !important;*/ } /* By default it's not affixed in mobile views, so undo that */ .dashboard-sidebar.affix { position: static; } @media (min-width: 768px) { .dashboard-sidebar { padding-left: 20px; } } /* First level of nav */ .dashboard-sidenav { margin-top: 20px; margin-bottom: 20px; } /* All levels of nav */ .dashboard-sidebar .nav > li > a { display: block; padding: 4px 20px; font-size: 13px; font-weight: 500; color: #767676; } .dashboard-sidebar .nav > li > a:hover, .dashboard-sidebar .nav > li > a:focus { padding-left: 19px; color: #563d7c; text-decoration: none; background-color: transparent; border-left: 1px solid #563d7c; } .dashboard-sidebar .nav > .active > a, .dashboard-sidebar .nav > .active:hover > a, .dashboard-sidebar .nav > .active:focus > a { padding-left: 18px; font-weight: bold; color: #563d7c; background-color: transparent; border-left: 2px solid #563d7c; } /* Nav: second level (shown on .active) */ .dashboard-sidebar .nav .nav { display: none; /* Hide by default, but at >768px, show it */ padding-bottom: 10px; } .dashboard-sidebar .nav .nav > li > a { padding-top: 1px; padding-bottom: 1px; padding-left: 30px; font-size: 12px; font-weight: normal; } .dashboard-sidebar .nav .nav > li > a:hover, .dashboard-sidebar .nav .nav > li > a:focus { padding-left: 29px; } .dashboard-sidebar .nav .nav > .active > a, .dashboard-sidebar .nav .nav > .active:hover > a, .dashboard-sidebar .nav .nav > .active:focus > a { padding-left: 28px; font-weight: 500; } .dropdown-menu { min-width: 200px; } .dropdown-menu.columns-2 { margin: 0; padding: 0; width: 400px; } .dropdown-menu li a { padding: 5px 15px; font-weight: 300; } .dropdown-menu.multi-column { overflow-x: hidden; } .multi-column-dropdown { list-style: none; padding: 0; } .multi-column-dropdown li a { display: block; clear: both; line-height: 1.428571429; white-space: normal; } .multi-column-dropdown li a:hover { text-decoration: none; color: #f5f5f5; background-color: #262626; } .scrollable-menu { height: auto; max-height: 80vh; overflow-x: hidden; } /* Back to top (hidden on mobile) */ .back-to-top, .dashboard-theme-toggle { display: none; padding: 4px 10px; margin-top: 10px; margin-left: 10px; font-size: 12px; font-weight: 500; color: #999; } .back-to-top:hover, .dashboard-theme-toggle:hover { color: #563d7c; text-decoration: none; } .dashboard-theme-toggle { margin-top: 0; } .container { width: calc(100% - 20px) !important; } .charts-body { display: inline-block; width: 100%; } .sidebar-body { position: absolute; display: none; } @media (min-width: 768px) { .charts-body { padding-left: 0%; padding-right: 0%; } .back-to-top, .dashboard-theme-toggle { display: block; } } /* Show and affix the side nav when space allows it */ @media (min-width: 992px) { .container { padding-left: 0% !important; } .charts-body { width: calc(100% - 213px) !important; padding-left: 1% !important; padding-right: 0% !important; } .sidebar-body { display: inline-block !important; width: 213px !important; } .dashboard-sidebar .nav > .active > ul { display: block; } /* Widen the fixed sidebar */ .dashboard-sidebar.affix, .dashboard-sidebar.affix-top, .dashboard-sidebar.affix-bottom { width: 213px !important; } .dashboard-sidebar.affix { position: fixed; /* Undo the static from mobile first approach */ top: 20px; } .dashboard-sidebar.affix-bottom { position: absolute; /* Undo the static from mobile first approach */ } .dashboard-sidebar.affix-bottom .dashboard-sidenav, .dashboard-sidebar.affix .dashboard-sidenav { margin-top: 0; margin-bottom: 0; } } @media (min-width: 1200px) { .container { padding-left: 2% !important; } .charts-body { width: calc(100% - 233px) !important; padding-left: 1% !important; padding-right: 1% !important; } .sidebar-body { display: inline-block !important; width: 233px !important; } /* Widen the fixed sidebar again */ .dashboard-sidebar.affix, .dashboard-sidebar.affix-top, .dashboard-sidebar.affix-bottom { width: 233px !important; } } @media (min-width: 1360px) { .container { padding-left: 3% !important; } .charts-body { width: calc(100% - 263px) !important; padding-left: 1% !important; padding-right: 2% !important; } .sidebar-body { display: inline-block !important; width: 263px !important; } /* Widen the fixed sidebar again */ .dashboard-sidebar.affix, .dashboard-sidebar.affix-top, .dashboard-sidebar.affix-bottom { width: 263px !important; } } </style> </head> <!-- check which theme to use --> <script type="text/javascript"> // enable alarms checking and notifications var netdataShowAlarms = true; // enable registry updates var netdataRegistry = true; // -------------------------------------------------------------------- // urlOptions var urlOptions = { hash: '#', theme: null, help: null, pan_and_zoom: false, after: 0, before: 0, nowelcome: false, show_alarms: false, chart: null, family: null, alarm: null, alarm_unique_id: 0, alarm_id: 0, alarm_event_id: 0, hasProperty: function(property) { // console.log('checking property ' + property + ' of type ' + typeof(this[property])); return typeof this[property] !== 'undefined'; } }; function netdataPanAndZoomCallback(status, after, before) { urlOptions.pan_and_zoom = status; urlOptions.after = after; urlOptions.before = before; netdataHashUpdate(); } function netdataHashUpdate() { history.replaceState(null, '', netdataHash()); } function netdataHash() { var hash = urlOptions.hash; if(urlOptions.pan_and_zoom === true) { hash += ';after=' + urlOptions.after.toString() + ';before=' + urlOptions.before.toString(); } if(urlOptions.theme !== null) hash += ';theme=' + urlOptions.theme.toString(); if(urlOptions.help !== null) hash += ';help=' + urlOptions.help.toString(); return hash; } function netdataHashParse() { var variables = document.location.hash.split(';'); var len = variables.length; while(len--) { if(len !== 0) { var p = variables[len].split('='); if(urlOptions.hasProperty(p[0]) && typeof p[1] !== 'undefined') urlOptions[p[0]] = decodeURIComponent(p[1]); } else { if(variables[len].length > 0) urlOptions.hash = variables[len]; } } var booleans = [ 'nowelcome', 'show_alarms', 'pan_and_zoom' ]; len = booleans.length; while(len--) { if(urlOptions[booleans[len]] === 'true' || urlOptions[booleans[len]] === true || urlOptions[booleans[len]] === '1' || urlOptions[booleans[len]] === 1) urlOptions[booleans[len]] = true; else urlOptions[booleans[len]] = false; } if(urlOptions.before > 0 && urlOptions.after > 0) { urlOptions.pan_and_zoom = true; urlOptions.nowelcome = true; } else urlOptions.pan_and_zoom = false; // console.log(urlOptions); } netdataHashParse(); // -------------------------------------------------------------------- // check options that should be processed before loading netdata.js function loadLocalStorage(name) { var ret = null; try { if(typeof Storage !== "undefined" && typeof localStorage === 'object') ret = localStorage.getItem(name); } catch(error) { ; } if(typeof ret === 'undefined' || ret === null) return null; // console.log('loaded: ' + name.toString() + ' = ' + ret.toString()); return ret; } function saveLocalStorage(name, value) { // console.log('saving: ' + name.toString() + ' = ' + value.toString()); try { if(typeof Storage !== "undefined" && typeof localStorage === 'object') { localStorage.setItem(name, value.toString()); return true; } } catch(error) { ; } return false; } function getTheme(def) { var ret = loadLocalStorage('netdataTheme'); if(typeof ret === 'undefined' || ret === null || ret === 'undefined') return def; else return ret; } function setTheme(theme) { if(theme === netdataTheme) return false; return saveLocalStorage('netdataTheme', theme); } var netdataTheme = getTheme('slate'); var netdataShowHelp = true; if(urlOptions.theme !== null) { setTheme(urlOptions.theme); netdataTheme = urlOptions.theme; } else urlOptions.theme = netdataTheme; if(urlOptions.help !== null) { saveLocalStorage('options.show_help', urlOptions.help); netdataShowHelp = urlOptions.help; } else { urlOptions.help = loadLocalStorage('options.show_help'); } // -------------------------------------------------------------------- // registry call back to render my-netdata menu var netdataRegistryCallback = function(machines_array) { var el = ''; var a1 = ''; var found = 0; if(machines_array === null) { var ret = loadLocalStorage("registryCallback"); if(typeof ret !== 'undefined' && ret !== null) { machines_array = JSON.parse(ret); console.log("failed to contact the registry - loaded registry data from browser local storage"); } } if(machines_array) { saveLocalStorage("registryCallback", JSON.stringify(machines_array)); var machines = machines_array.sort(function (a, b) { if (a.name > b.name) return -1; if (a.name < b.name) return 1; return 0; }); var len = machines.length; while(len--) { var u = machines[len]; found++; el += '<li id="registry_server_' + u.guid + '"><a class="registry_link" href="' + u.url + '" onClick="return gotoServerModalHandler(\'' + u.guid + '\');">' + u.name + '</a></li>'; 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>'; } } if(!found) { if(machines) 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>'; else 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>'; a1 += '<li><a href="#" onClick="return false;"> </a></li>'; el += '<li role="separator" class="divider"></li>' + '<li><a href="//london.netdata.rocks/default.html">UK - London (DigitalOcean.com)</a></li>' + '<li><a href="//newyork.netdata.rocks/default.html">US - New York (DigitalOcean.com)</a></li>' + '<li><a href="//sanfrancisco.netdata.rocks/default.html">US - San Francisco (DigitalOcean.com)</a></li>' + '<li><a href="//atlanta.netdata.rocks/default.html">US - Atlanta (CDN77.com)</a></li>' + '<li><a href="//frankfurt.netdata.rocks/default.html">Germany - Frankfurt (DigitalOcean.com)</a></li>' + '<li><a href="//toronto.netdata.rocks/default.html">Canada - Toronto (DigitalOcean.com)</a></li>' + '<li><a href="//singapore.netdata.rocks/default.html">Japan - Singapore (DigitalOcean.com)</a></li>' + '<li><a href="//bangalore.netdata.rocks/default.html">India - Bangalore (DigitalOcean.com)</a></li>'; a1 += '<li role="separator" class="divider"></li>' + '<li><a href="#"> </a></li>' + '<li><a href="#"> </a></li>'+ '<li><a href="#"> </a></li>'+ '<li><a href="#"> </a></li>'+ '<li><a href="#"> </a></li>'+ '<li><a href="#"> </a></li>'+ '<li><a href="#"> </a></li>'+ '<li><a href="#"> </a></li>'; } el += '<li role="separator" class="divider"></li>'; a1 += '<li role="separator" class="divider"></li>'; el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #999;" target="_blank">What is this?</a></li>'; 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>' document.getElementById('mynetdata_servers').innerHTML = el; document.getElementById('mynetdata_servers2').innerHTML = el; document.getElementById('mynetdata_actions1').innerHTML = a1; gotoServerInit(); }; var this_is_demo = null; function isdemo() { if(this_is_demo !== null) return this_is_demo; this_is_demo = false; try { if(typeof document.location.hostname === 'string') { if(document.location.hostname.endsWith('.my-netdata.io') || document.location.hostname.endsWith('.mynetdata.io') || document.location.hostname.endsWith('.netdata.rocks') || document.location.hostname.endsWith('.firehol.org') || document.location.hostname.endsWith('.netdata.online')) this_is_demo = true; } } catch(error) { ; } return this_is_demo; } function netdataURL(url) { if(typeof url === 'undefined') url = document.location.toString(); if(url.indexOf('#') !== -1) url = url.substring(0, url.indexOf('#')); var hash = netdataHash(); // console.log('netdataURL: ' + url + hash); return url + hash; } function netdataReload(url) { var t = netdataURL(url); // console.log('netdataReload: ' + t); document.location = t; // since we play with hash // this is needed to reload the page location.reload(); } var gotoServerValidateRemaining = 0; var gotoServerMiddleClick = false; var gotoServerStop = false; function gotoServerValidateUrl(id, guid, url) { var penaldy = 0; var error = 'failed'; if(document.location.toString().startsWith('http://') && url.toString().startsWith('https://')) // we penalize https only if the current url is http // to allow the user walk through all its servers. penaldy = 500; else if(document.location.toString().startsWith('https://') && url.toString().startsWith('http://')) error = 'can\'t check'; var finalURL = netdataURL(url); setTimeout(function() { 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>'; NETDATA.registry.hello(url, function(data) { if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid === guid) { // console.log('OK ' + id + ' URL: ' + url); document.getElementById(guid + '-' + id + '-status').innerHTML = "OK"; if(!gotoServerStop) { gotoServerStop = true; if(gotoServerMiddleClick) { window.open(finalURL, '_blank'); gotoServerMiddleClick = false; 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)'; } else { document.getElementById('gotoServerResponse').innerHTML += 'found it! It is at:<br/><small>' + url + '</small>'; document.location = finalURL; } } } else { if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid !== guid) error = 'wrong machine'; document.getElementById(guid + '-' + id + '-status').innerHTML = error; gotoServerValidateRemaining--; if(gotoServerValidateRemaining <= 0) { gotoServerMiddleClick = false; document.getElementById('gotoServerResponse').innerHTML = '<b>Sorry! I cannot find any operational URL for this server</b>'; } } }); }, (id * 50) + penaldy); } function gotoServerModalHandler(guid) { // console.log('goto server: ' + guid); gotoServerStop = false; var checked = {}; var len = NETDATA.registry.machines[guid].alternate_urls.length; var count = 0; document.getElementById('gotoServerResponse').innerHTML = ''; document.getElementById('gotoServerList').innerHTML = ''; document.getElementById('gotoServerName').innerHTML = NETDATA.registry.machines[guid].name; $('#gotoServerModal').modal('show'); gotoServerValidateRemaining = len; while(len--) { var url = NETDATA.registry.machines[guid].alternate_urls[len]; checked[url] = true; gotoServerValidateUrl(count++, guid, url); } setTimeout(function() { if(gotoServerStop === false) { document.getElementById('gotoServerResponse').innerHTML = '<b>Added all the known URLs for this machine.</b>'; NETDATA.registry.search(guid, function(data) { // console.log(data); len = data.urls.length; while(len--) { var url = data.urls[len][1]; // console.log(url); if(typeof checked[url] === 'undefined') { gotoServerValidateRemaining++; checked[url] = true; gotoServerValidateUrl(count++, guid, url); } } }); } }, 2000); return false; } function gotoServerInit() { $(".registry_link").on('click', function(e) { if(e.which === 2) { e.preventDefault(); gotoServerMiddleClick = true; } else { gotoServerMiddleClick = false; } return true; }); } function switchRegistryModalHandler() { document.getElementById('switchRegistryPersonGUID').value = NETDATA.registry.person_guid; document.getElementById('switchRegistryURL').innerHTML = NETDATA.registry.server; document.getElementById('switchRegistryResponse').innerHTML = ''; $('#switchRegistryModal').modal('show'); } function notifyForSwitchRegistry() { var n = document.getElementById('switchRegistryPersonGUID').value; if(n !== '' && n.length === 36) { NETDATA.registry.switch(n, function(result) { if(result !== null) { $('#switchRegistryModal').modal('hide'); NETDATA.registry.init(); } else { document.getElementById('switchRegistryResponse').innerHTML = "<b>Sorry! The registry rejected your request.</b>"; } }); } else document.getElementById('switchRegistryResponse').innerHTML = "<b>The ID you have entered is not a GUID.</b>"; } var deleteRegistryUrl = null; function deleteRegistryModalHandler(guid, name, url) { deleteRegistryUrl = url; document.getElementById('deleteRegistryServerName').innerHTML = name; document.getElementById('deleteRegistryServerName2').innerHTML = name; document.getElementById('deleteRegistryServerURL').innerHTML = url; document.getElementById('deleteRegistryResponse').innerHTML = ''; $('#deleteRegistryModal').modal('show'); } function notifyForDeleteRegistry() { if(deleteRegistryUrl) { NETDATA.registry.delete(deleteRegistryUrl, function(result) { if(result !== null) { deleteRegistryUrl = null; $('#deleteRegistryModal').modal('hide'); NETDATA.registry.init(); } else { document.getElementById('deleteRegistryResponse').innerHTML = "<b>Sorry! this command was rejected by the registry server.</b>"; } }); } } var options = { sparklines_registry: {}, menus: {}, submenu_names: {}, data: null, hostname: 'netdata_server', // will be overwritten by the netdata server categories: new Array(), categories_idx: {}, families: new Array(), families_idx: {}, chartsPerRow: 0, chartsMinWidth: 1450, chartsHeight: 180, sparklinesHeight: 60, }; // generate a sparkline // used in the documentation function sparkline(chart, dimension, units) { var key = chart + '.' + dimension; if(typeof units === 'undefined') units = ''; if(typeof options.sparklines_registry[key] === 'undefined') options.sparklines_registry[key] = { count: 1 }; else options.sparklines_registry[key].count++; key = key + '.' + options.sparklines_registry[key].count; var h = '<div data-netdata="' + chart + '" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dimensions="' + dimension + '" data-show-value-of-' + dimension + '-at="' + key + '"></div> (<span id="' + key + '" style="display: inline-block; min-width: 50px; text-align: right;">X</span>' + units + ')'; return h; } function chartsPerRow(total) { if(options.chartsPerRow === 0) { width = Math.floor(total / options.chartsMinWidth); if(width === 0) width = 1; return width; } else return options.chartsPerRow; } function prioritySort(a, b) { if(a.priority < b.priority) return -1; if(a.priority > b.priority) return 1; if(a.name < b.name) return -1; return 1; } function sortObjectByPriority(object) { var idx = {}; var sorted = new Array(); for(var i in object) { if(typeof idx[i] === 'undefined') { idx[i] = object[i]; sorted.push(i); } } sorted.sort(function(a, b) { if(idx[a].priority < idx[b].priority) return -1; if(idx[a].priority > idx[b].priority) return 1; if(a < b) return -1; return 1; }); return sorted; } // ---------------------------------------------------------------------------- // scroll to a section, without changing the browser history function scrollToId(hash) { if(hash && hash != '') { var offset = $('#' + hash).offset(); if(typeof offset !== 'undefined') $('html, body').animate({ scrollTop: offset.top }, 0); } // we must return false to prevent the default action return false; } // ---------------------------------------------------------------------------- var netdataDashboard = { menu: {}, submenu: {}, context: {}, gaugeChart: function(title, width, dimensions, colors) { if(typeof colors === 'undefined') colors = ''; if(typeof dimensions === 'undefined') dimensions = ''; return '<div data-netdata="CHART_UNIQUE_ID"' + ' data-dimensions="' + dimensions + '"' + ' data-chart-library="gauge"' + ' data-gauge-adjust="width"' + ' data-title="' + title + '"' + ' data-width="' + width + '"' + ' data-before="0"' + ' data-after="-CHART_DURATION"' + ' data-points="CHART_DURATION"' + ' data-colors="' + colors + '"' + ' role="application"></div>'; }, anyAttribute: function(obj, attr, key, def) { if(typeof obj[key] !== 'undefined') { if(typeof obj[key][attr] !== 'undefined') return obj[key][attr]; } return def; }, menuTitle: function(chart) { if(typeof chart.menu_pattern !== 'undefined') { return (netdataDashboard.anyAttribute(netdataDashboard.menu, 'title', chart.menu_pattern, chart.menu_pattern).toString() + ' ' + chart.type.slice(-(chart.type.length - chart.menu_pattern.length - 1)).toString()).replace(/_/g, ' '); } return (netdataDashboard.anyAttribute(netdataDashboard.menu, 'title', chart.menu, chart.menu)).toString().replace(/_/g, ' '); }, menuIcon: function(chart) { if(typeof chart.menu_pattern !== 'undefined') return netdataDashboard.anyAttribute(netdataDashboard.menu, 'icon', chart.menu_pattern, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>').toString(); return netdataDashboard.anyAttribute(netdataDashboard.menu, 'icon', chart.menu, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>'); }, menuInfo: function(menu) { return netdataDashboard.anyAttribute(netdataDashboard.menu, 'info', menu, null); }, menuHeight: function(menu, relative) { return netdataDashboard.anyAttribute(netdataDashboard.menu, 'height', menu, 1.0) * relative; }, submenuTitle: function(menu, submenu) { var key = menu + '.' + submenu; var title = netdataDashboard.anyAttribute(netdataDashboard.submenu, 'title', key, submenu).toString().replace(/_/g, ' ');; if(title.length > 28) { var a = title.substring(0, 13); var b = title.substring(title.length - 12, title.length); return a + '...' + b; } return title; }, submenuInfo: function(menu, submenu) { var key = menu + '.' + submenu; return netdataDashboard.anyAttribute(netdataDashboard.submenu, 'info', key, null); }, submenuHeight: function(menu, submenu, relative) { var key = menu + '.' + submenu; return netdataDashboard.anyAttribute(netdataDashboard.submenu, 'height', key, 1.0) * relative; }, contextInfo: function(id) { if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].info !== 'undefined') return '<div class="chart-message netdata-chart-alignment" role="document">' + netdataDashboard.context[id].info + '</div>'; else return ''; }, contextHeight: function(id, def) { if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].height !== 'undefined') return def * netdataDashboard.context[id].height; else return def; } }; // ---------------------------------------------------------------------------- // enrich the data structure returned by netdata // to reflect our menu system and content function enrichChartData(chart) { var tmp = chart.type.split('_')[0]; switch(tmp) { case 'ap': case 'net': case 'disk': chart.menu = tmp; break; case 'cgroup': chart.menu = chart.type; if(chart.id.match(/.*[\._\/-:]qemu[\._\/-:]*/) || chart.id.match(/.*[\._\/-:]kvm[\._\/-:]*/)) chart.menu_pattern = 'cgqemu'; else chart.menu_pattern = 'cgroup'; break; case 'apache': case 'exim': case 'memcached': case 'mysql': case 'named': case 'nginx': case 'nut': case 'phpfpm': case 'postfix': case 'redis': case 'retroshare': case 'ipfs': case 'smawebbox': case 'squid': case 'snmp': case 'tomcat': chart.menu = chart.type; chart.menu_pattern = tmp; break; case 'tc': chart.menu = tmp; // find a name for this device from fireqos info // we strip '_(in|out)' or '(in|out)_' if(typeof options.submenu_names[chart.family] === 'undefined' || options.submenu_names[chart.family] === chart.family) { var n = chart.name.split('.')[1]; if(n.endsWith('_in')) options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_in')); else if(n.endsWith('_out')) options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_out')); else if(n.startsWith('in_')) options.submenu_names[chart.family] = n.slice(3, n.length); else if(n.startsWith('out_')) options.submenu_names[chart.family] = n.slice(4, n.length); } // increase the priority of IFB devices // to have inbound appear before outbound if(chart.id.match(/.*-ifb$/)) chart.priority--; break; default: chart.menu = chart.type; break; } chart.submenu = chart.family; } // ---------------------------------------------------------------------------- function headMain(charts, duration) { var head = ''; if(typeof charts['system.swap'] !== 'undefined') head += '<div style="margin-right: 10px;" data-netdata="system.swap"' + ' data-dimensions="free"' + ' data-append-options="percentage"' + ' data-chart-library="easypiechart"' + ' data-title="Free Swap"' + ' data-units="%"' + ' data-easypiechart-max-value="100"' + ' data-width="8%"' + ' data-before="0"' + ' data-after="-' + duration.toString() + '"' + ' data-points="' + duration.toString() + '"' + ' data-colors="#DD4400"' + ' role="application"></div>'; if(typeof charts['system.io'] !== 'undefined') { head += '<div style="margin-right: 10px;" data-netdata="system.io"' + ' data-dimensions="in"' + ' data-chart-library="easypiechart"' + ' data-title="Disk Read"' + ' data-width="10%"' + ' data-before="0"' + ' data-after="-' + duration.toString() + '"' + ' data-points="' + duration.toString() + '"' + ' role="application"></div>'; head += '<div style="margin-right: 10px;" data-netdata="system.io"' + ' data-dimensions="out"' + ' data-chart-library="easypiechart"' + ' data-title="Disk Write"' + ' data-width="10%"' + ' data-before="0"' + ' data-after="-' + duration.toString() + '"' + ' data-points="' + duration.toString() + '"' + ' role="application"></div>'; } if(typeof charts['system.cpu'] !== 'undefined') head += '<div data-netdata="system.cpu"' + ' data-chart-library="gauge"' + ' data-title="CPU"' + ' data-units="%"' + ' data-gauge-max-value="100"' + ' data-width="18%"' + ' data-after="-' + duration.toString() + '"' + ' data-points="' + duration.toString() + '"' + ' data-colors="' + NETDATA.colors[12] + '"' + ' role="application"></div>'; if(typeof charts['system.ipv4'] !== 'undefined') { head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"' + ' data-dimensions="received"' + ' data-chart-library="easypiechart"' + ' data-title="IPv4 Inbound"' + ' data-width="10%"' + ' data-before="0"' + ' data-after="-' + duration.toString() + '"' + ' data-points="' + duration.toString() + '"' + ' role="application"></div>'; head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"' + ' data-dimensions="sent"' + ' data-chart-library="easypiechart"' + ' data-title="IPv4 Outbound"' + ' data-width="10%"' + ' data-before="0"' + ' data-after="-' + duration.toString() + '"' + ' data-points="' + duration.toString() + '"' + ' role="application"></div>'; } else if(typeof charts['system.ipv6'] !== 'undefined') { head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"' + ' data-dimensions="received"' + ' data-chart-library="easypiechart"' + ' data-title="IPv6 Inbound"' + ' data-units="kbps"' + ' data-width="10%"' + ' data-before="0"' + ' data-after="-' + duration.toString() + '"' + ' data-points="' + duration.toString() + '"' + ' role="application"></div>'; head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"' + ' data-dimensions="sent"' + ' data-chart-library="easypiechart"' + ' data-title="IPv6 Outbound"' + ' data-units="kbps"' + ' data-width="10%"' + ' data-before="0"' + ' data-after="-' + duration.toString() + '"' + ' data-points="' + duration.toString() + '"' + ' role="application"></div>'; } if(typeof charts['system.ram'] !== 'undefined') head += '<div style="margin-right: 10px;" data-netdata="system.ram"' + ' data-dimensions="cached|free"' + ' data-append-options="percentage"' + ' data-chart-library="easypiechart"' + ' data-title="Available RAM"' + ' data-units="%"' + ' data-easypiechart-max-value="100"' + ' data-width="8%"' + ' data-after="-' + duration.toString() + '"' + ' data-points="' + duration.toString() + '"' + ' data-colors="' + NETDATA.colors[7] + '"' + ' role="application"></div>'; return head; } function generateHeadCharts(type, chart, duration) { var head = ''; var hcharts = netdataDashboard.anyAttribute(netdataDashboard.context, type, chart.context, []); if(hcharts.length > 0) { var hi = 0, hlen = hcharts.length; while(hi < hlen) { if(typeof hcharts[hi] === 'function') head += hcharts[hi](chart.id).replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id); else head += hcharts[hi].replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id); hi++; } } return head; } function renderPage(menus, data) { var div = document.getElementById('charts_div'); var pcent_width = Math.floor(100 / chartsPerRow($(div).width())); // find the proper duration for per-second updates var duration = Math.round(($(div).width() * pcent_width / 100 * data.update_every / 3) / 60) * 60; var html = ''; var sidebar = '<ul class="nav dashboard-sidenav" data-spy="affix" id="sidebar_ul">'; var mainhead = headMain(data.charts, duration); // sort the menus var main = sortObjectByPriority(menus); var i = 0, len = main.length; while(i < len) { var menu = main[i++]; // generate an entry at the main menu var menuid = NETDATA.name2id('menu_' + menu); sidebar += '<li class=""><a href="#' + menuid + '" onClick="return scrollToId(\'' + menuid + '\');">' + menus[menu].icon + ' ' + menus[menu].title + '</a><ul class="nav">'; html += '<div role="section"><div role="sectionhead"><h1 id="' + menuid + '" role="heading">' + menus[menu].title + '</h1></div><div role="document">'; if(menus[menu].info !== null) html += menus[menu].info; // console.log(' >> ' + menu + ' (' + menus[menu].priority + '): ' + menus[menu].title); var shtml = ''; var mhead = '<div class="netdata-chart-row">' + mainhead; mainhead = ''; // sort the submenus of this menu var sub = sortObjectByPriority(menus[menu].submenus); var si = 0, slen = sub.length; while(si < slen) { var submenu = sub[si++]; // generate an entry at the submenu var submenuid = NETDATA.name2id('menu_' + menu + '_submenu_' + submenu); sidebar += '<li class><a href="#' + submenuid + '" onClick="return scrollToId(\'' + submenuid + '\');">' + menus[menu].submenus[submenu].title + '</a></li>'; 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>'; if(menus[menu].submenus[submenu].info !== null) shtml += '<div class="chart-message netdata-chart-alignment" role="document">' + menus[menu].submenus[submenu].info + '</div>'; var head = '<div class="netdata-chart-row">'; var chtml = ''; // console.log(' \------- ' + submenu + ' (' + menus[menu].submenus[submenu].priority + '): ' + menus[menu].submenus[submenu].title); // sort the charts in this submenu of this menu menus[menu].submenus[submenu].charts.sort(prioritySort); var ci = 0, clen = menus[menu].submenus[submenu].charts.length; while(ci < clen) { var chart = menus[menu].submenus[submenu].charts[ci++]; // generate the submenu heading charts mhead += generateHeadCharts('mainheads', chart, duration); head += generateHeadCharts('heads', chart, duration); // generate the chart chtml += netdataDashboard.contextInfo(chart.context) + '<div id="chart_' + NETDATA.name2id(chart.id) + '" data-netdata="' + chart.id + '"' + ' data-width="' + pcent_width.toString() + '%"' + ' data-height="' + netdataDashboard.contextHeight(chart.context, options.chartsHeight).toString() + 'px"' + ' data-before="0"' + ' data-after="-' + duration.toString() + '"' + ' data-id="' + NETDATA.name2id(options.hostname + '/' + chart.id) + '"' + ' data-colors="' + netdataDashboard.anyAttribute(netdataDashboard.context, 'colors', chart.context, '') + '"' + ' role="application"></div>'; // console.log(' \------- ' + chart.id + ' (' + chart.priority + '): ' + chart.context + ' height: ' + menus[menu].submenus[submenu].height); } head += '</div>'; shtml += head + chtml + '</div>'; } mhead += '</div>'; sidebar += '</ul></li>'; html += mhead + shtml + '</div></div><hr role="separator"/>'; } sidebar += '</ul>'; div.innerHTML = html; document.getElementById('sidebar').innerHTML = sidebar; finalizePage(); } function renderChartsAndMenu(data) { var menus = options.menus; var charts = data.charts; for(var c in charts) { enrichChartData(charts[c]); // create the menu if(typeof menus[charts[c].menu] === 'undefined') { menus[charts[c].menu] = { priority: charts[c].priority, submenus: {}, title: netdataDashboard.menuTitle(charts[c]), icon: netdataDashboard.menuIcon(charts[c]), info: netdataDashboard.menuInfo(charts[c].menu), height: netdataDashboard.menuHeight(charts[c].menu, options.chartsHeight) }; } if(charts[c].priority < menus[charts[c].menu].priority) menus[charts[c].menu].priority = charts[c].priority; // create the submenu if(typeof menus[charts[c].menu].submenus[charts[c].submenu] === 'undefined') { menus[charts[c].menu].submenus[charts[c].submenu] = { priority: charts[c].priority, charts: new Array(), title: null, info: netdataDashboard.submenuInfo(charts[c].menu, charts[c].submenu), height: netdataDashboard.submenuHeight(charts[c].menu, charts[c].submenu, menus[charts[c].menu].height) }; } if(charts[c].priority < menus[charts[c].menu].submenus[charts[c].submenu].priority) menus[charts[c].menu].submenus[charts[c].submenu].priority = charts[c].priority; // index the chart in the menu/submenu menus[charts[c].menu].submenus[charts[c].submenu].charts.push(charts[c]); } // propagate the descriptive subname given to QoS // to all the other submenus with the same name for(var m in menus) { for(var s in menus[m].submenus) { // set the family using a name if(typeof options.submenu_names[s] !== 'undefined') { menus[m].submenus[s].title = s + ' (' + options.submenu_names[s] + ')'; } else { menus[m].submenus[s].title = netdataDashboard.submenuTitle(m, s); } } } renderPage(menus, data); } // ---------------------------------------------------------------------------- function loadJs(url, callback) { $.ajax({ url: url, cache: true, dataType: "script", xhrFields: { withCredentials: true } // required for the cookie }) .fail(function() { alert('Cannot load required JS library: ' + url); }) .always(function() { if(typeof callback === 'function') callback(); }) } var bootstrapTableLoaded = false; function loadBootstrapTable(callback) { if(bootstrapTableLoaded === false) { bootstrapTableLoaded === true; loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-1.11.0.min.js', function() { loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-export-1.11.0.min.js', function() { loadJs(NETDATA.serverDefault + 'lib/tableExport-1.6.0.min.js', callback); }) }); } else callback(); } function alarmsUpdateModal() { var active = '<h3>Raised Alarms</h3><table class="table">'; var all = '<h3>All Running Alarms</h3><div class="panel-group" id="alarms_all_accordion" role="tablist" aria-multiselectable="true">'; 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.'; NETDATA.alarms.get('all', function(data) { options.alarm_families = new Array(); alarmsCallback(data); if(data === null) { document.getElementById('alarms_active').innerHTML = document.getElementById('alarms_all').innerHTML = document.getElementById('alarms_log').innerHTML = 'failed to load alarm data!'; return; } function timestamp4human(timestamp, space) { if(typeof space === 'undefined') space = ' '; var t = new Date(timestamp * 1000); var now = new Date(); if(t.toDateString() == now.toDateString()) return t.toLocaleTimeString(); return t.toLocaleDateString() + space + t.toLocaleTimeString(); } function seconds4human(seconds, options) { var default_options = { now: 'now', space: ' ', negative_suffix: 'ago', hour: 'hour', hours: 'hours', minute: 'minute', minutes: 'minutes', second: 'second', seconds: 'seconds', and: 'and' }; if(typeof options !== 'object') options = default_options; else { var x; for(x in default_options) { if(typeof options[x] !== 'string') options[x] = default_options[x]; } } if(typeof seconds === 'string') seconds = parseInt(seconds); if(seconds === 0) return options.now; var suffix = ''; if(seconds < 0) { seconds = -seconds; if(options.negative_suffix !== '') suffix = options.space + options.negative_suffix; } var hours = Math.floor(seconds / 3600); seconds -= (hours * 3600); var minutes = Math.floor(seconds / 60); seconds -= (minutes * 60); var txt = ''; if(hours > 1) txt += hours.toString() + options.space + options.hours; else if(hours === 1) txt += hours.toString() + options.space + options.hour; if(hours > 0 && minutes > 0 && seconds == 0) txt += options.space + options.and + options.space; else if(hours > 0 && minutes > 0 && seconds > 0) txt += ',' + options.space; if(minutes > 1) txt += minutes.toString() + options.space + options.minutes; else if(minutes === 1) txt += minutes.toString() + options.space + options.minute; if((minutes > 0 || minutes > 0) && seconds > 0) txt += options.space + options.and + options.space; if(seconds > 1) txt += Math.floor(seconds).toString() + options.space + options.seconds; else if(seconds === 1) txt += Math.floor(seconds).toString() + options.space + options.second; return txt + suffix; } function alarm_lookup_explain(alarm, chart) { var dimensions = ' of all values '; if(chart.dimensions.length > 1) dimensions = ' of the sum of all dimensions '; if(typeof alarm.lookup_dimensions !== 'undefined') { var d = alarm.lookup_dimensions.replace('|', ','); var x = d.split(','); if(x.length > 1) dimensions = 'of the sum of dimensions <code>' + alarm.lookup_dimensions + '</code> '; else dimensions = 'of all values of dimension <code>' + alarm.lookup_dimensions + '</code> '; } return '<code>' + alarm.lookup_method + '</code> ' + dimensions + ', of chart <code>' + alarm.chart + '</code>' + ', starting <code>' + seconds4human(alarm.lookup_after + alarm.lookup_before) + '</code> and up to <code>' + seconds4human(alarm.lookup_before) + '</code>' + ((alarm.lookup_options)?(', with options <code>' + alarm.lookup_options.replace(' ', ', ') + '</code>'):'') + '.'; } function alarm_to_html(alarm, full) { var chart = options.data.charts[alarm.chart]; 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><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></td>' + '<td><table class="table">' + ((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>'):'') + ((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>'):''); if(full === true) { 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>'):'') + ((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>'):'') + ((chart.green !== null)?('<tr><td width="10%" style="text-align:right">green threshold</td><td><code>' + chart.green + ' ' + chart.units + '</code></td></tr>'):'') + ((chart.red !== null)?('<tr><td width="10%" style="text-align:right">red threshold</td><td><code>' + chart.red + ' ' + chart.units + '</code></td></tr>'):''); } var delay = ''; if((alarm.delay_up_duration > 0 || alarm.delay_down_duration > 0) && alarm.delay_multiplier != 0 && alarm.delay_max_duration > 0) { if(alarm.delay_up_duration == alarm.delay_down_duration) { delay += '<small><br/>hysteresis ' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' }); } else { delay = '<small><br/>hysteresis '; if(alarm.delay_up_duration > 0) { delay += 'on escalation <code>' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' }) + '</code>, '; } if(alarm.delay_down_duration > 0) { delay += 'on recovery <code>' + seconds4human(alarm.delay_down_duration, { negative_suffix: '' }) + '</code>, '; } } if(alarm.delay_multiplier != 1.0) { delay += 'multiplied by <code>' + alarm.delay_multiplier.toString() + '</code>'; delay += ', up to <code>' + seconds4human(alarm.delay_max_duration, { negative_suffix: '' }) + '</code>'; } delay += '</small>'; } html += '<tr><td width="10%" style="text-align:right">check every</td><td>' + seconds4human(alarm.update_every, { negative_suffix: '' }) + '</td></tr>' + '<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span>' + delay + '</td></tr>' + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>' + '</table></td></tr>'; return html; } function alarm_family_show(id) { var html = '<table class="table">'; var family = options.alarm_families[id]; var len = family.arr.length; while(len--) { var alarm = family.arr[len]; html += alarm_to_html(alarm, true); } html += '</table>'; $('#alarm_all_' + id.toString()).html(html); } // find the proper family of each alarm var now = new Date().getTime(); var x; var count_active = 0; var count_all = 0; var families = {}; var families_sort = new Array(); for(x in data.alarms) { var alarm = data.alarms[x]; var family = alarm.family; // find the chart var chart = options.data.charts[alarm.chart]; if(typeof chart === 'undefined') chart = options.data.charts_by_name[alarm.chart]; // not found - this should never happen! if(typeof chart === 'undefined') { console.log('WARNING: alarm ' + x + ' is linked to chart ' + alarm.chart + ', which is not found in the list of chart got from the server.'); chart = { priority: 9999999 }; } else if(typeof chart.menu !== 'undefined' && typeof chart.submenu !== 'undefined') // the family based on the chart family = chart.menu + ' - ' + chart.submenu; if(typeof families[family] === 'undefined') { families[family] = { name: family, arr: new Array(), priority: chart.priority }; families_sort.push(families[family]); } if(chart.priority < families[family].priority) families[family].priority = chart.priority; families[family].arr.unshift(alarm); } // sort the families, like the dashboard menu does var families_sorted = families_sort.sort(function (a, b) { if (a.priority > b.priority) return -1; if (a.priority < b.priority) return 1; return 0; }); var fc = 0; var len = families_sorted.length; while(len--) { var family = families_sorted[len].name; var active_family_added = false; var expanded = 'true'; var collapsed = ''; var cin = 'in'; if(fc !== 0) { all += "</table></div></div></div>"; expanded = 'false'; collapsed = 'class="collapsed"' cin = ''; } 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() + '">'; options.alarm_families[fc] = families[family]; fc++; var arr = families[family].arr; var c = arr.length; while(c--) { var alarm = arr[c]; if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') { if(!active_family_added) { active_family_added = true; active += '<tr><th class="text-center" colspan="2"><h4>' + family + '</h4></th></tr>'; } count_active++; active += alarm_to_html(alarm, true); } count_all++; } } active += "</table>"; if(families_sorted.length > 0) all += "</div></div></div>"; all += "</div>"; if(!count_active) active += "<h4>Everything is normal. No raised alarms.</h4>"; else active += footer; if(!count_all) all += "<h4>No alarms are running in this system.</h4>"; else all += footer; document.getElementById('alarms_active').innerHTML = active; document.getElementById('alarms_all').innerHTML = all; if(families_sorted.length > 0) alarm_family_show(0); // register bootstrap events $('#alarms_all_accordion').on('show.bs.collapse', function (d) { var target = $(d.target); var id = $(target).data('alarm-id'); alarm_family_show(id); }); $('#alarms_all_accordion').on('hidden.bs.collapse', function (d) { var target = $(d.target); var id = $(target).data('alarm-id'); $('#alarm_all_' + id.toString()).html(''); }); document.getElementById('alarms_log').innerHTML = '<h3>Alarm Log</h3><table id="alarms_log_table"></table>'; loadBootstrapTable(function () { $('#alarms_log_table').bootstrapTable({ url: NETDATA.alarms.server + '/api/v1/alarm_log?all', cache: false, pagination: true, pageSize: 10, showPaginationSwitch: false, search: true, searchTimeOut: 300, searchAlign: 'left', showColumns: true, showExport: true, exportDataType: 'basic', exportOptions: { fileName: 'netdata_alarm_log' }, rowStyle: function(row, index) { switch(row.status) { case 'CRITICAL' : return { classes: 'danger' }; break; case 'WARNING' : return { classes: 'warning' }; break; case 'UNDEFINED': return { classes: 'info' }; break; case 'CLEAR' : return { classes: 'success' }; break; } return {}; }, showFooter: false, showHeader: true, showRefresh: true, showToggle: false, sortable: true, silentSort: false, columns: [ { field: 'when', title: 'Event Date', valign: 'middle', titleTooltip: 'The date and time the even took place', switchable: false, sortable: true, formatter: function(value, row, index) { return timestamp4human(value, ' '); }, }, { field: 'hostname', title: 'Host', valign: 'middle', titleTooltip: 'The host that generated this event', visible: false, sortable: true }, { field: 'unique_id', title: 'Unique ID', titleTooltip: 'The host unique ID for this event', valign: 'middle', visible: false, sortable: true }, { field: 'alarm_id', title: 'Alarm ID', titleTooltip: 'The ID of the alarm that generated this event', valign: 'middle', visible: false, sortable: true }, { field: 'alarm_event_id', title: 'Alarm Event ID', titleTooltip: 'The incremental ID of this event for the given alarm', valign: 'middle', visible: false, sortable: true }, { field: 'chart', title: 'Chart', titleTooltip: 'The chart the alarm is attached to', valign: 'middle', switchable: false, sortable: true }, { field: 'family', title: 'Family', titleTooltip: 'The family of the chart the alarm is attached to', valign: 'middle', visible: false, sortable: true }, { field: 'name', title: 'Alarm', titleTooltip: 'The alarm name that generated this event', formatter: function(value, row, index) { return value.toString().replace(/_/g, ' '); }, valign: 'middle', switchable: false, sortable: true }, { field: 'old_value', title: 'Old Value', titleTooltip: 'The value of the alarm, just before this event', valign: 'middle', visible: false, sortable: true }, { field: 'value', title: 'Value', titleTooltip: 'The value of the alarm, that triggered this event', formatter: function(value, row, index) { return ((value !== null)?Math.floor(value):'NaN').toString(); }, align: 'right', valign: 'middle', sortable: true }, { field: 'units', title: 'Units', titleTooltip: 'The units of the value of the alarm', valign: 'middle', sortable: true }, { field: 'old_status', title: 'Old Status', titleTooltip: 'The status of the alarm, just before this event', valign: 'middle', visible: false, sortable: true }, { field: 'status', title: 'Status', titleTooltip: 'The status of the alarm, that was set due to this event', valign: 'middle', switchable: false, sortable: true }, { field: 'duration', title: 'Last Duration', titleTooltip: 'The duration the alarm was at its previous state, just before this event', formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); }, valign: 'middle', visible: false, sortable: true }, { field: 'non_clear_duration', title: 'Raised Duration', titleTooltip: 'The duration the alarm was raised, just before this event', formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); }, valign: 'middle', visible: false, sortable: true }, { field: 'recipient', title: 'Recipient', titleTooltip: 'The recipient of this event', valign: 'middle', visible: false, sortable: true }, { field: 'processed', title: 'Processed Status', titleTooltip: 'True when this event is processed', valign: 'middle', visible: false, sortable: true }, { field: 'updated', title: 'Updated Status', titleTooltip: 'True when this event has been updated by another event', valign: 'middle', visible: false, sortable: true }, { field: 'updated_by_id', title: 'Updated By ID', titleTooltip: 'The unique ID of the event that obsoleted this one', valign: 'middle', visible: false, sortable: true }, { field: 'updates_id', title: 'Updates ID', titleTooltip: 'The unique ID of the event obsoleted because of this event', valign: 'middle', visible: false, sortable: true }, { field: 'exec', title: 'Script', titleTooltip: 'The script to handle the event notification', valign: 'middle', visible: false, sortable: true }, { field: 'exec_run', title: 'Script Run At', titleTooltip: 'The date and time the script has been ran', formatter: function(value, row, index) { return timestamp4human(value, ' '); }, valign: 'middle', visible: false, sortable: true }, { field: 'exec_code', title: 'Script Return Value', titleTooltip: 'The return code of the script', valign: 'middle', visible: false, sortable: true }, { field: 'delay', title: 'Script Delay', titleTooltip: 'The hysteresis of the notification', formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); }, valign: 'middle', visible: false, sortable: true }, { field: 'delay_up_to_timestamp', title: 'Script Delay Run At', titleTooltip: 'The date and time the script should be run, after hysteresis', formatter: function(value, row, index) { return timestamp4human(value, ' '); }, valign: 'middle', visible: false, sortable: true }, { field: 'info', title: 'Description', titleTooltip: 'A short description of the alarm', valign: 'middle', visible: false, sortable: true }, { field: 'source', title: 'Alarm Source', titleTooltip: 'The source of configuration of the alarm', valign: 'middle', visible: false, sortable: true } ] }); // console.log($('#alarms_log_table').bootstrapTable('getOptions')); }); }); } function alarmsCallback(data) { var count = 0; for(x in data.alarms) { var alarm = data.alarms[x]; if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') count++; } if(count > 0) document.getElementById('alarms_count_badge').innerHTML = count.toString(); else document.getElementById('alarms_count_badge').innerHTML = ''; } function initializeDynamicDashboard(netdata_url) { if(typeof netdata_url === 'undefined' || netdata_url === null) netdata_url = NETDATA.serverDefault; // initialize clickable alarms NETDATA.alarms.chart_div_offset = 100; NETDATA.alarms.chart_div_id_prefix = 'chart_'; NETDATA.alarms.chart_div_animation_duration = 0; NETDATA.pause(function() { NETDATA.alarms.callback = alarmsCallback; // download all the charts the server knows NETDATA.chartRegistry.downloadAll(netdata_url, function(data) { if(data !== null) { options.hostname = data.hostname; options.data = data; // update the dashboard hostname document.getElementById('hostname').innerHTML = options.hostname; document.getElementById('hostname').href = NETDATA.serverDefault; // update the dashboard title document.title = options.hostname + ' netdata dashboard'; // close the splash screen $("#loadOverlay").css("display","none"); // create a chart_by_name index data.charts_by_name = {}; var charts = data.charts; var x; for(x in charts) { var chart = charts[x]; data.charts_by_name[chart.name] = chart; } // render all charts renderChartsAndMenu(data); } }); }); } // ---------------------------------------------------------------------------- function versionLog(msg) { document.getElementById('versionCheckLog').innerHTML = msg; } function getNetdataVersion(callback) { versionLog('Downloading installed version info from netdata...'); $.ajax({ url: 'version.txt', async: true, cache: false, xhrFields: { withCredentials: true } // required for the cookie }) .done(function(data) { data = data.replace(/(\r\n|\n|\r| |\t)/gm,""); if(data.length !== 40) { versionLog('Received version string is invalid.'); callback(null); } else { versionLog('Installed version of netdata is ' + data); document.getElementById('netdataVersion').innerHTML = data; callback(data); } }) .fail(function() { versionLog('Failed to download installed version info from netdata!'); callback(null); }); } function getGithubLatestCommit(callback) { versionLog('Downloading latest version info from github...'); $.ajax({ url: 'https://api.github.com/repos/firehol/netdata/commits', async: true, cache: false }) .done(function(data) { versionLog('Latest version info from github is ' + data[0].sha); callback(data[0].sha); }) .fail(function() { versionLog('Failed to download installed version info from github!'); callback(null); }); } function checkForUpdate(callback) { getNetdataVersion(function(sha1) { if(sha1 === null) callback(null, null); getGithubLatestCommit(function(sha2) { callback(sha1, sha2); }); }); return null; } function notifyForUpdate(force) { versionLog('<p>checking for updates...</p>'); var now = new Date().getTime(); if(typeof force === 'undefined' || force !== true) { var last = loadLocalStorage('last_update_check'); if(typeof last === 'string') last = parseInt(last); else last = 0; if(now - last < 3600000 * 8) { // no need to check it - too soon return; } } checkForUpdate(function(sha1, sha2) { var save = false; if(sha1 === null) { save = false; versionLog('<p><big>Failed to get your netdata version!</big></p><p>You can always get the latest version of netdata from <a href="https://github.com/firehol/netdata" target="_blank">its github page</a>.</p>'); } else if(sha2 === null) { save = false; versionLog('<p><big>Failed to get the latest version from github.</big></p><p>You can always get the latest version of netdata from <a href="https://github.com/firehol/netdata" target="_blank">its github page</a>.</p>'); } else if(sha1 === sha2) { save = true; versionLog('<p><big>You already have the latest version of netdata!</big></p><p>No update yet?<br/>Probably, we need some motivation to keep going on!</p><p>If you haven\'t already, <a href="https://github.com/firehol/netdata" target="_blank">give netdata a <b>Star</b> at its github page</a>.</p>'); } else { save = true; var compare = 'https://github.com/firehol/netdata/compare/' + sha1.toString() + '...' + sha2.toString(); versionLog('<p><big><strong>New version of netdata available!</strong></big></p><p>Latest version: ' + sha2.toString() + '</p><p><a href="' + compare + '" target="_blank">Click here for the changes log</a> since your installed version, and<br/><a href="https://github.com/firehol/netdata/wiki/Updating-Netdata" target="_blank">click here for directions on updating</a> your netdata installation.</p><p>We suggest to review the changes log for new features you may be interested, or important bug fixes you may need.<br/>Keeping your netdata updated, is generally a good idea.</p>'); document.getElementById('update_badge').innerHTML = '!'; } if(save) saveLocalStorage('last_update_check', now.toString()); }); } // ---------------------------------------------------------------------------- function finalizePage() { // resize all charts - without starting the background thread // this has to be done while NETDATA is paused // if we ommit this, the affix menu will be wrong, since all // the Dom elements are initially zero-sized NETDATA.parseDom(); if(urlOptions.pan_and_zoom === true) NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before); // ------------------------------------------------------------------------ // https://github.com/viralpatel/jquery.shorten/blob/master/src/jquery.shorten.js $.fn.shorten = function(settings) { "use strict"; var config = { showChars: 750, minHideChars: 10, ellipsesText: "...", moreText: '<i class="fa fa-expand" aria-hidden="true"></i> show more information', lessText: '<i class="fa fa-compress" aria-hidden="true"></i> show less information', onLess: function() { NETDATA.onscroll(); }, onMore: function() { NETDATA.onscroll(); }, errMsg: null, force: false }; if (settings) { $.extend(config, settings); } if ($(this).data('jquery.shorten') && !config.force) { return false; } $(this).data('jquery.shorten', true); $(document).off("click", '.morelink'); $(document).on({ click: function() { var $this = $(this); if ($this.hasClass('less')) { $this.removeClass('less'); $this.html(config.moreText); $this.parent().prev().animate({'height':'0'+'%'}, 0, function () { $this.parent().prev().prev().show(); }).hide(0, function() { config.onLess(); }); } else { $this.addClass('less'); $this.html(config.lessText); $this.parent().prev().animate({'height':'100'+'%'}, 0, function () { $this.parent().prev().prev().hide(); }).show(0, function() { config.onMore(); }); } return false; } }, '.morelink'); return this.each(function() { var $this = $(this); var content = $this.html(); var contentlen = $this.text().length; if (contentlen > config.showChars + config.minHideChars) { var c = content.substr(0, config.showChars); if (c.indexOf('<') >= 0) // If there's HTML don't want to cut it { var inTag = false; // I'm in a tag? var bag = ''; // Put the characters to be shown here var countChars = 0; // Current bag size var openTags = []; // Stack for opened tags, so I can close them later var tagName = null; for (var i = 0, r = 0; r <= config.showChars; i++) { if (content[i] == '<' && !inTag) { inTag = true; // This could be "tag" or "/tag" tagName = content.substring(i + 1, content.indexOf('>', i)); // If its a closing tag if (tagName[0] == '/') { if (tagName != '/' + openTags[0]) { config.errMsg = 'ERROR en HTML: the top of the stack should be the tag that closes'; } else { openTags.shift(); // Pops the last tag from the open tag stack (the tag is closed in the retult HTML!) } } else { // There are some nasty tags that don't have a close tag like <br/> if (tagName.toLowerCase() != 'br') { openTags.unshift(tagName); // Add to start the name of the tag that opens } } } if (inTag && content[i] == '>') { inTag = false; } if (inTag) { bag += content.charAt(i); } // Add tag name chars to the result else { r++; if (countChars <= config.showChars) { bag += content.charAt(i); // Fix to ie 7 not allowing you to reference string characters using the [] countChars++; } else // Now I have the characters needed { if (openTags.length > 0) // I have unclosed tags { //console.log('They were open tags'); //console.log(openTags); for (j = 0; j < openTags.length; j++) { //console.log('Cierro tag ' + openTags[j]); bag += '</' + openTags[j] + '>'; // Close all tags that were opened // 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 } break; } } } } c = $('<div/>').html(bag + '<span class="ellip">' + config.ellipsesText + '</span>').html(); }else{ c+=config.ellipsesText; } var html = '<div class="shortcontent">' + c + '</div><div class="allcontent">' + content + '</div><span><a href="javascript://nop/" class="morelink">' + config.moreText + '</a></span>'; $this.html(html); $this.find(".allcontent").hide(); // Hide all text $('.shortcontent p:last', $this).css('margin-bottom', 0); //Remove bottom margin on last paragraph as it's likely shortened } }); }; $(".chart-message").shorten(); // ------------------------------------------------------------------------ // callback for us to track PanAndZoom operations NETDATA.globalPanAndZoom.callback = netdataPanAndZoomCallback; // let it run (update the charts) NETDATA.unpause(); // check if we have to jump to a specific section scrollToId(urlOptions.hash.replace('#','')); if(urlOptions.chart !== null) { NETDATA.alarms.scrollToChart(urlOptions.chart); //urlOptions.hash = '#' + NETDATA.name2id('menu_' + charts[c].menu + '_submenu_' + charts[c].submenu); //urlOptions.hash = '#chart_' + NETDATA.name2id(urlOptions.chart); //console.log('hash = ' + urlOptions.hash); } /* activate bootstrap sidebar (affix) */ $('#sidebar').affix({ offset: { top: (isdemo())?150:0, bottom: 0 } }); /* fix scrolling of very long affix lists http://stackoverflow.com/questions/21691585/bootstrap-3-1-0-affix-too-long */ $('#sidebar').on('affixed.bs.affix', function() { $(this).removeAttr('style'); }); /* activate bootstrap scrollspy (needed for sidebar) */ $(document.body).scrollspy({ target: '#sidebar', offset: $(window).height() / 5 // controls the diff of the <hX> element to the top, to select it }); // change the URL based on the current position of the screen $('#sidebar').on('activate.bs.scrollspy', function (e) { // console.log(e); var el = $(e.target); //if(el.find('ul').size() == 0) { var hash = el.find('a').attr('href'); if(typeof hash === 'string' && hash.substring(0, 1) === '#' && urlOptions.hash.startsWith(hash + '_submenu_') === false) { urlOptions.hash = hash; //console.log(urlOptions.hash); netdataHashUpdate(); } //else console.log('hash: not accepting ' + hash); //} //else console.log('el.find(): not found'); }); document.getElementById('footer').style.display = 'block'; var update_options_modal = function() { // console.log('update_options_modal'); var sync_option = function(option) { var self = $('#' + option); if(self.prop('checked') !== NETDATA.getOption(option)) { // console.log('switching ' + option.toString()); self.bootstrapToggle(NETDATA.getOption(option)?'on':'off'); } } var theme_sync_option = function(option) { var self = $('#' + option); self.bootstrapToggle(netdataTheme === 'slate'?'on':'off'); } sync_option('eliminate_zero_dimensions'); sync_option('destroy_on_hide'); sync_option('async_on_scroll'); sync_option('parallel_refresher'); sync_option('concurrent_refreshes'); sync_option('sync_selection'); sync_option('sync_pan_and_zoom'); sync_option('stop_updates_when_focus_is_lost'); sync_option('smooth_plot'); sync_option('pan_and_zoom_data_padding'); sync_option('show_help'); theme_sync_option('netdata_theme_control'); if(NETDATA.getOption('parallel_refresher') === false) { $('#concurrent_refreshes_row').hide(); } else { $('#concurrent_refreshes_row').show(); } }; NETDATA.setOption('setOptionCallback', update_options_modal); // handle options changes $('#eliminate_zero_dimensions').change(function() { NETDATA.setOption('eliminate_zero_dimensions', $(this).prop('checked')); }); $('#destroy_on_hide').change(function() { NETDATA.setOption('destroy_on_hide', $(this).prop('checked')); }); $('#async_on_scroll').change(function() { NETDATA.setOption('async_on_scroll', $(this).prop('checked')); }); $('#parallel_refresher').change(function() { NETDATA.setOption('parallel_refresher', $(this).prop('checked')); }); $('#concurrent_refreshes').change(function() { NETDATA.setOption('concurrent_refreshes', $(this).prop('checked')); }); $('#sync_selection').change(function() { NETDATA.setOption('sync_selection', $(this).prop('checked')); }); $('#sync_pan_and_zoom').change(function() { NETDATA.setOption('sync_pan_and_zoom', $(this).prop('checked')); }); $('#stop_updates_when_focus_is_lost').change(function() { NETDATA.setOption('stop_updates_when_focus_is_lost', $(this).prop('checked')); }); $('#smooth_plot').change(function() { NETDATA.setOption('smooth_plot', $(this).prop('checked')); }); $('#pan_and_zoom_data_padding').change(function() { NETDATA.setOption('pan_and_zoom_data_padding', $(this).prop('checked')); }); $('#show_help').change(function() { urlOptions.help = $(this).prop('checked'); NETDATA.setOption('show_help', urlOptions.help); netdataReload(); }); // this has to be the last // it reloads the page $('#netdata_theme_control').change(function() { urlOptions.theme = $(this).prop('checked')?'slate':'white'; if(setTheme(urlOptions.theme)) netdataReload(); }); $('#updateModal').on('shown.bs.modal', function() { notifyForUpdate(true); }); $('#alarmsModal').on('shown.bs.modal', function() { NETDATA.pause(alarmsUpdateModal); }); $('#alarmsModal').on('hidden.bs.modal', function() { NETDATA.unpause(); document.getElementById('alarms_active').innerHTML = document.getElementById('alarms_all').innerHTML = document.getElementById('alarms_log').innerHTML = 'loading...'; }); $('#deleteRegistryModal').on('hidden.bs.modal', function() { deleteRegistryGuid = null; }); if(isdemo()) { if(urlOptions.nowelcome !== true) { setTimeout(function() { $('#welcomeModal').modal(); }, 1000); } // google analytics when this is used for the home page of the demo sites // this does not run on user's installations setTimeout(function() { (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-64295674-3', 'auto'); ga('send', 'pageview'); }, 2000); } else notifyForUpdate(); if(urlOptions.show_alarms === true) setTimeout(function() { $('#alarmsModal').modal('show'); }, 1000); } function resetDashboardOptions() { var help = NETDATA.options.current.show_help; NETDATA.resetOptions(); if(setTheme('slate')) netdataReload(); if(help !== NETDATA.options.current.show_help) netdataReload(); } // callback to add the dashboard info to the // parallel javascript downloader in netdata var netdataPrepCallback = function() { NETDATA.requiredCSS.push({ url: NETDATA.serverDefault + 'css/bootstrap-toggle-2.2.2.min.css', isAlreadyLoaded: function() { return false; } }); NETDATA.requiredJs.push({ url: NETDATA.serverDefault + 'lib/bootstrap-toggle-2.2.2.min.js', isAlreadyLoaded: function() { return false; } }); NETDATA.requiredJs.push({ url: NETDATA.serverDefault + 'dashboard_info.js?v20161002-1', async: false, isAlreadyLoaded: function() { return false; } }); if(isdemo()) { document.getElementById('masthead').style.display = 'block'; } } // our entry point var netdataCallback = initializeDynamicDashboard; </script> <body data-spy="scroll" data-target="#sidebar"> <div id="loadOverlay" class="loadOverlay" style="background-color: #888; color: #888;"> netdata<br/><div style="font-size: 3vh;">Real-time performance monitoring, done right!</div> </div> <script type="text/javascript"> // change the loadOverlay colors ASAP to match the theme document.getElementById('loadOverlay').style = (urlOptions.theme === 'slate')?"background-color:#272b30; color: #373b40;":"background-color:#fff; color: #ddd;"; </script> <nav class="navbar navbar-default navbar-fixed-top" role="banner"> <div class="container"> <nav id="mynetdata_nav" class="collapse navbar-collapse navbar-left hidden-sm hidden-xs" role="navigation" style="padding-right: 20px;"> <ul class="nav navbar-nav"> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" id="current_view">my-netdata <strong class="caret"></strong></a> <ul class="dropdown-menu scrollable-menu inpagemenu multi-column columns-2" role="menu"> <div class="row"> <div class="col-sm-6" style="width: 85%; padding-right: 0;"> <ul id="mynetdata_servers" class="multi-column-dropdown"> <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li> </ul> </div> <div class="col-sm-3 hidden-xs" style="width: 15%; padding-left: 0;"> <ul id="mynetdata_actions1" class="multi-column-dropdown"> <li style="color: #999;"> </li> </ul> </div> </div> </ul> </li> </ul> </nav> <div class="navbar-header"> <button class="navbar-toggle" type="button" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a href="/" class="navbar-brand" id="hostname" title="reload the dashboard">netdata</a> </div> <nav class="collapse navbar-collapse navbar-right" role="navigation"> <ul class="nav navbar-nav"> <li><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal" title="alarms"><i class="fa fa-bell"></i></span> <span class="hidden-sm">Alarms </span><span id="alarms_count_badge" class="badge"></a></li> <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> <li><a href="https://github.com/firehol/netdata/wiki" class="btn" target="_blank" title="netdata community"><i class="fa fa-github"></i> <span class="hidden-sm hidden-md">Community</span></a></li> <li class="hidden-sm" id="updateButton"><a href="#" class="btn" data-toggle="modal" data-target="#updateModal" title="check for update"><i class="fa fa-cloud-download"></i><span id="update_badge" class="badge"></span> <span class="hidden-sm hidden-md">Update</span></a></li> <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> <!-- <li class="dropdown hidden-md hidden-lg hidden-xs"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" id="current_view">Menu <strong class="caret"></strong></a> <ul class="dropdown-menu scrollable-menu inpagemenu" role="menu"> <li><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal"><i class="fa fa-bell"></i> alarms</a></li> <li><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal"><i class="fa fa-sliders"></i> settings</a></li> <li><a href="https://github.com/firehol/netdata/wiki" class="btn" target="_blank"><i class="fa fa-github"></i> community</a></li> <li><a href="#" class="btn" data-toggle="modal" data-target="#helpModal"><i class="fa fa-question-circle"></i> help</a></li> </ul> </li> --> <li class="dropdown hidden-sm hidden-md hidden-lg"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" id="current_view">my-netdata <strong class="caret"></strong></a> <ul id="mynetdata_servers2" class="dropdown-menu scrollable-menu inpagemenu" role="menu"> <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li> </ul> </li> </ul> </nav> </nav> </div> </nav> <div id="masthead" style="display: none;"> <div class="container"> <div class="row"> <div class="col-md-7"> <h1>Netdata <p class="lead">Real-time performance monitoring, in the greatest possible detail</p> </h1> </div> <div class="col-md-5"> <div class="well well-lg"> <div class="row"> <div class="col-md-6"> <b>Drag</b> charts to pan. <b>Shift + wheel</b> on them, to zoom in and out. <b>Double-click</b> on them, to reset. <b>Hover</b> on them too! </div> <div class="col-md-6"> <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> </div> </div> </div> </div> </div> </div> </div> <div class="container"> <div class="row"> <div class="charts-body" role="main"> <div id="charts_div"></div> </div> <div class="sidebar-body hidden-xs hidden-sm" role="complementary"> <nav class="dashboard-sidebar hidden-print hidden-xs hidden-sm" id="sidebar" role="menu"></nav> </div> </div> </div> <div id="footer" class="container" style="display: none;"> <div class="row"> <div class="col-md-10" role="main"> <div class="p"> <big><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></big><br/> <i class="fa fa-copyright"></i> Copyright 2016, Costa Tsaousis.<br/> Released under <a href="http://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">GPL v3 or later</a>.<br/> </div> <div class="p"> <small> <a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a> re-distributes these software tools: <i class="fa fa-circle"></i> The excellent <a href="http://dygraphs.com/" target="_blank">Dygraphs.com</a> web chart library, <i class="fa fa-copyright"></i> Copyright 2009, Dan Vanderkam, <a href="http://dygraphs.com/legal.html" target="_blank">MIT License</a> <i class="fa fa-circle"></i> <a href="https://rendro.github.io/easy-pie-chart/" target="_blank">Easy Pie Chart</a> web chart library, <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> <i class="fa fa-circle"></i> <a href="http://bernii.github.io/gauge.js/" target="_blank">Gauge.js</a> web chart library, <i class="fa fa-copyright"></i> Copyright, Bernard Kobos, <a href="http://bernii.github.io/gauge.js/" target="_blank">MIT License</a> <i class="fa fa-circle"></i> <a href="https://jquery.org/" target="_blank">jQuery</a>, <i class="fa fa-copyright"></i> Copyright 2015, jQuery Foundation, <a href="https://jquery.org/license/" target="_blank">MIT License</a> <i class="fa fa-circle"></i> <a href="http://getbootstrap.com/getting-started/" target="_blank">Bootstrap</a>, <i class="fa fa-copyright"></i> Copyright 2015, Twitter, <a href="http://getbootstrap.com/getting-started/#license-faqs" target="_blank">MIT License</a> <i class="fa fa-circle"></i> <a href="http://www.bootstraptoggle.com/" target="_blank">Bootstrap Toggle</a>, <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> <i class="fa fa-circle"></i> <a href="https://jamesflorentino.github.io/nanoScrollerJS/" target="_blank">NanoScroller</a>, <i class="fa fa-copyright"></i> Copyright 2012, James Florentino, <a href="https://github.com/jamesflorentino/nanoScrollerJS/blob/master/LICENSE" target="_blank">MIT License</a> <i class="fa fa-circle"></i> <a href="https://fortawesome.github.io/Font-Awesome/" target="_blank">FontAwesome</a>, <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> <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. <i class="fa fa-circle"></i> <a href="http://bootstrap-table.wenzhixin.net.cn/" target="_blank">bootstrap-table</a>, <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> <i class="fa fa-circle"></i> <a href="https://github.com/hhurz/tableExport.jquery.plugin" target="_blank">tableExport.jquery.plugin</a>, <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> </small> </div> </div> </div> </div> <div class="modal fade" id="welcomeModal" tabindex="-1" role="dialog" aria-labelledby="welcomeModalLabel"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="welcomeModalLabel">Welcome!</h4> </div> <div class="modal-body"> <div class="p"> <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> is the fastest way to visualize metrics. It is a resource efficient, highly optimized system for collecting and visualizing any type of real-time time series data, from CPU usage, disk activity, SQL queries, API calls, web site visitors, etc. </div> <div class="p"> <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> tries to visualize the truth of <b>now</b>, in its <b>greatest detail</b>, so that you can get insights of what is happening now and what just happened, on your systems and applications. </div> <div class="p"> To make a chart in <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>, you just need a <b>number</b>. Just a number you can read somehow. <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> will turn this number to a real time, interactive, web chart. For collecting these numbers, it supports <a href="https://github.com/firehol/netdata/wiki/External-Plugins" target="_blank">external plugins</a>, even <a href="https://github.com/firehol/netdata/wiki/General-Info---charts.d" target="_blank">shell</a> or <a href="https://github.com/firehol/netdata/wiki/General-Info---charts.d" target="_blank">node.js</a> plugins. Any computer program, in any language, that can print a few lines of text on its standard output, can be a netdata data collector. </div> <div class="p"> <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> can embed charts everywhere, like this one <div data-netdata="system.cpu" data-dimensions="system" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-show-value-of-system-at="system.cpu.system.modal.1"></div> (my CPU system usage which is <span id="system.cpu.system.modal.1" style="display: inline-block; width: 40px; text-align: right;"></span>%), or this one <div data-netdata="ipv4.tcppackets" data-dimensions="received" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-show-value-of-received-at="ipv4.tcppackets.received.modal.1"></div> (my IPv4 received TCP packets, which are <span id="ipv4.tcppackets.received.modal.1" style="display: inline-block; width: 60px; text-align: right;"></span>/second). </div> <div class="p"> You can have <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> charts on your site too. Just give it a <code>div</code> and a real time chart, zoomable and draggable will appear (try it even on these tiny ones - <b>drag</b> them to pan horizontally, <b>shift + drag</b> to zoom in, on <b>chrome shift + mouse wheel</b> to zoom in/out, <b>double click</b> on them to reset them - don't be afraid of <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> performance - <a href="https://github.com/firehol/netdata/wiki/Performance" target="_blank">a raspberry pi 2 can sustain 300 charts updates per second</a>!). </div> <div class="p"> For more information please refer to the <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata wiki</a></b>. </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div> </div> </div> <div class="modal fade" id="helpModal" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="helpModalLabel">Dashboard Help</h4> </div> <div class="modal-body"> <h4>Dygraphs (line, area and stacked area charts)</h4> <!-- Nav tabs --> <ul class="nav nav-tabs" role="tablist"> <li role="presentation" class="active"><a href="#help_mouse" aria-controls="help_mouse" role="tab" data-toggle="tab">Mouse Interface</a></li> <li role="presentation"><a href="#help_touch" aria-controls="help_touch" role="tab" data-toggle="tab">Touch Interface</a></li> </ul> <!-- Tab panes --> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="help_mouse"> <div class="p"> <h4>Mouse Over / Hover</h4> 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). <br/> All the other visible charts will also show and highlight their values for the same timestamp. </div> <hr/> <div class="p"> <h4>Drag Chart Contents</h4> Drag the contents of a chart to pan it horizontally. <br/> 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). <br/> Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double click</b> a panned chart. </div> <hr/> <div class="p"> <h4>Double Click</h4> Double Click a chart to reset all the charts to their default auto-refreshing state. </div> <hr/> <div class="p"> <h4>SHIFT + Drag</h4> 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: <ul> <li>The already loaded chart contents are zoomed (low resolution)</li> <li>New data are transferred from the netdata server, to refresh the chart with possibly more detail.</li> </ul> Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart. </div> <hr/> <div class="p"> <h4>SHIFT + Mouse Wheel <small>(does not work on firefox and IE/Edge)</small></h4> 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. <br/> Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart. </div> <hr/> <div class="p"> <h4>Legend Operations</h4> Click on the label or value of a dimension, will select / un-select this dimension. <br/> You can press any of the SHIFT or CONTROL keys and then click on legend labels or values, to select / un-select multiple dimensions. </div> </div> <div role="tabpanel" class="tab-pane" id="help_touch"> <div class="p"> <h4>Single Tap</h4> 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). <br/> All the other visible charts will also show and highlight their values for the same timestamp. </div> <hr/> <div class="p"> <h4>Drag Chart Contents</h4> Touch and Drag the contents of a chart to pan it horizontally. <br/> 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). <br/> Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double tap</b> a panned chart. </div> <hr/> <div class="p"> <h4>Double Tap</h4> Double tap a chart to reset all the charts to their default auto-refreshing state. </div> <hr/> <div class="p"> <h4>Zoom <small>(does not work on firefox and IE/Edge)</small></h4> With two fingers, zoom in or out. <br/> Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart. </div> <hr/> <div class="p"> <h4>Legend Operations</h4> Tap on the label or value of a dimension, will select / un-select this dimension. </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div> </div> </div> <div class="modal fade" id="alarmsModal" tabindex="-1" role="dialog" aria-labelledby="alarmsModalLabel"> <div class="modal-dialog modal-lg" role="document" style="display: table;"> <!-- allow the modal to expand horizontally --> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="alarmsModalLabel">netdata alarms</h4> </div> <div class="modal-body"> <!-- Nav tabs --> <ul class="nav nav-tabs" role="tablist"> <li role="presentation" class="active"><a href="#alarms_active" aria-controls="alarms_active" role="tab" data-toggle="tab">Active</a></li> <li role="presentation"><a href="#alarms_all" aria-controls="alarms_all" role="tab" data-toggle="tab">All</a></li> <li role="presentation"><a href="#alarms_log" aria-controls="alarms_log" role="tab" data-toggle="tab">Log</a></li> </ul> <!-- Tab panes --> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="alarms_active"> loading... </div> <div role="tabpanel" class="tab-pane" id="alarms_all"> loading... </div> <div role="tabpanel" class="tab-pane" id="alarms_log"> loading... </div> </div> </div> <div class="modal-footer"> <!-- <a href="#" onclick="alarmsUpdateModal(); return false;" type="button" class="btn btn-default">Update</a> --> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div> </div> </div> <div class="modal fade" id="optionsModal" tabindex="-1" role="dialog" aria-labelledby="optionsModalLabel"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="optionsModalLabel">netdata dashboard options</h4> </div> <div class="modal-body"> <center> <small style="color: #BBBBBB;">These are browser settings. Each viewer has its own. They do not affect the operation of your netdata server. <br/> Settings take effect immediately and are saved permanently to browser local storage (except the refresh on focus / always option). <br/> To reset all options (including charts sizes) to their defaults, click <a href="#" onclick="resetDashboardOptions(); return false;">here</a>.</small> </center> <div style="padding: 10px;"></div> <!-- Nav tabs --> <ul class="nav nav-tabs" role="tablist"> <li role="presentation" class="active"><a href="#settings_performance" aria-controls="settings_performance" role="tab" data-toggle="tab">Performance</a></li> <li role="presentation"><a href="#settings_sync" aria-controls="settings_sync" role="tab" data-toggle="tab">Synchronization</a></li> <li role="presentation"><a href="#settings_visual" aria-controls="settings_visual" role="tab" data-toggle="tab">Visual</a></li> </ul> <!-- Tab panes --> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="settings_performance"> <form id="optionsForm1" method="get" class="form-horizontal"> <div class="form-group"> <table> <tr class="option-row"> <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> <td class="option-info"><strong>When to refresh the charts?</strong><br/> <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> </td> </tr> <tr class="option-row"> <td class="option-control"> <input id="eliminate_zero_dimensions" type="checkbox" checked data-toggle="toggle" data-on="Non Zero" data-off="All" data-width="110px"> </td> <td class="option-info"><strong>Which dimensions to show?</strong><br/> <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> </td> </tr> <tr class="option-row"> <td class="option-control"><input id="destroy_on_hide" type="checkbox" data-toggle="toggle" data-on="Destroy" data-off="Hide" data-width="110px"></td> <td class="option-info"><strong>How to handle hidden charts?</strong><br/> <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> </td> </tr> <tr class="option-row"> <td class="option-control"><input id="async_on_scroll" type="checkbox" data-toggle="toggle" data-on="Async" data-off="Sync" data-width="110px"></td> <td class="option-info"><strong>Page scroll handling?</strong><br/> <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> </td> </tr> </table> </div> </form> </div> <div role="tabpanel" class="tab-pane" id="settings_sync"> <form id="optionsForm2" method="get" class="form-horizontal"> <div class="form-group"> <table> <tr class="option-row"> <td class="option-control"><input id="parallel_refresher" type="checkbox" checked data-toggle="toggle" data-on="Parallel" data-off="Sequential" data-width="110px"></td> <td class="option-info"><strong>Which chart refresh policy to use?</strong><br/> <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> </td> </tr> <tr class="option-row" id="concurrent_refreshes_row"> <td class="option-control"></td> <td class="option-info"> <table> <tr class="option-row"> <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> <td class="option-info"> <strong>Shall we re-sync chart refreshes?</strong><br/> <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> </td> </tr> </table> </td> </tr> <tr class="option-row"> <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> <td class="option-info"><strong>Sync hover selection on all charts?</strong><br/> <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> </td> </tr> <tr class="option-row"> <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> <td class="option-info"><strong>Sync pan and zoom on all charts?</strong><br/> <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> </td> </tr> </table> </div> </form> </div> <div role="tabpanel" class="tab-pane" id="settings_visual"> <form id="optionsForm3" method="get" class="form-horizontal"> <div class="form-group"> <table> <tr class="option-row"> <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> <td class="option-info"><strong>Which theme to use?</strong><br/> <small>Netdata comes with two themes: <b>Dark</b> (the default) and <b>White</b>. <br/> <b>Switching this will reload the dashboard</b>. </small> </td> </tr> <tr class="option-row"> <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> <td class="option-info"><strong>Do you need help?</strong><br/> <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. <br/> <b>Switching this will reload the dashboard</b>. </small> </td> </tr> <tr class="option-row"> <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> <td class="option-info"><strong>Enable data padding when panning and zooming?</strong><br/> <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> </td> </tr> <tr class="option-row"> <td class="option-control"><input id="smooth_plot" type="checkbox" checked data-toggle="toggle" data-on="Smooth" data-off="Rough" data-width="110px"></td> <td class="option-info"><strong>Enable Bézier lines on charts?</strong><br/> <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. <br/> 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> </td> </tr> </table> </div> </form> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div> </div> </div> <div class="modal fade" id="updateModal" tabindex="-1" role="dialog" aria-labelledby="updateModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="updateModalLabel">Update Check</h4> </div> <div class="modal-body"> Your netdata version: <b><code><span id="netdataVersion">Unknown</span></code></b> <br/> <div style="padding: 10px;"></div> <div id="versionCheckLog">Not checked yet. Please press the Check Now button.</div> </div> <div class="modal-footer"> <a href="#" onclick="notifyForUpdate(true); return false;" type="button" class="btn btn-default">Check Now</a> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div> </div> </div> <div class="modal fade" id="deleteRegistryModal" tabindex="-1" role="dialog" aria-labelledby="deleteRegistryModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="deleteRegistryModalLabel">Delete <span id="deleteRegistryServerName"></span>?</h4> </div> <div class="modal-body"> You are about to delete, from your personal list of netdata servers, the following server: <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;"> <b><span id="deleteRegistryServerName2"></span></b> <br/> <b><span id="deleteRegistryServerURL"></span></b> </p> Are you sure you want to do this? <br/> <div style="padding: 10px;"></div> <small>Keep in mind, this server will be added back if and when you visit it again.</small> <br/> <div id="deleteRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div> </div> <div class="modal-footer"> <button type="button" class="btn btn-success" data-dismiss="modal">keep it</button> <a href="#" onclick="notifyForDeleteRegistry(true); return false;" type="button" class="btn btn-danger">delete it</a> </div> </div> </div> </div> <div class="modal fade" id="switchRegistryModal" tabindex="-1" role="dialog" aria-labelledby="switchRegistryModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="switchRegistryModalLabel">Switch Netdata Registry Identity</h4> </div> <div class="modal-body"> You can copy and paste the following ID to all your browsers (e.g. work and home). <br/> All the browsers with the same ID will identify <b>you</b>, so please don't share this with others. <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;"> <form action="#"> <input type="text" class="form-control" id="switchRegistryPersonGUID" placeholder="your personal ID" maxlength="36" autocomplete="off" style="text-align: center; font-size: 1.4em;"> </form> </p> Either copy this ID and paste it to another browser, or paste here the ID you have taken from another browser. <p style="padding-top: 10px;"><small> Keep in mind that: <ul> <li>when you switch ID, your previous ID will be lost forever - this is irreversible.</li> <li>both IDs (your old and the new) must list this netdata at their personal lists.</li> <li>both IDs have to be known by the registry: <b><span id="switchRegistryURL"></span></b>.</li> <li>to get a new ID, just clear your browser cookies.</li> </ul> </small></p> <div id="switchRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div> </div> <div class="modal-footer"> <button type="button" class="btn btn-success" data-dismiss="modal">cancel</button> <a href="#" onclick="notifyForSwitchRegistry(true); return false;" type="button" class="btn btn-danger">impersonate</a> </div> </div> </div> </div> <div class="modal fade" id="gotoServerModal" tabindex="-1" role="dialog" aria-labelledby="gotoServerModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="gotoServerModalLabel"><span id="gotoServerName"></span></h4> </div> <div class="modal-body"> Checking known URLs for this server... <div style="padding-top: 20px;"> <table id="gotoServerList"> </table> </div> <p style="padding-top: 10px;"><small> Checks may fail if you are viewing an HTTPS page and the server to be checked is HTTP only. </small></p> <div id="gotoServerResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div> </div> </div> </body> </html> <script type="text/javascript" src="dashboard.js?v20161004-1"></script>