diff options
Diffstat (limited to 'web/index.html')
-rw-r--r-- | web/index.html | 3926 |
1 files changed, 2051 insertions, 1875 deletions
diff --git a/web/index.html b/web/index.html index e305cf6f..d8e12823 100644 --- a/web/index.html +++ b/web/index.html @@ -29,13 +29,21 @@ <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." /> + <meta property="og:locale" content="en_US" /> + <meta property="og:url" content="https://my-netdata.io" /> + <meta property="og:type" content="website" /> + <meta property="og:site_name" content="netdata"/> + <meta property="og:title" content="Get control of your Linux Servers. Simple. Effective. Awesome." /> + <meta property="og:description" content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms." /> + <meta property="og:image" content="https://cloud.githubusercontent.com/assets/2662304/20910305/65d10354-bb69-11e6-8128-c44b547517b4.png" /> + <meta property="og:image:type" content="image/png" /> + <meta property="fb:app_id" content="1200089276712916" /> + + <meta name="twitter:card" content="summary" /> + <meta name="twitter:site" content="@linuxnetdata" /> + <meta name="twitter:title" content="Get control of your Linux Servers. Simple. Effective. Awesome." /> + <meta name="twitter:description" content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms." /> + <meta name="twitter:image" content="https://cloud.githubusercontent.com/assets/2662304/14092712/93b039ea-f551-11e5-822c-beadbf2b2a2e.gif" /> <style> /* prevent body from hiding under the navbar */ @@ -177,6 +185,10 @@ font-weight: 500; color: #767676; } + .dashboard-sidebar .nav > li > a > .fa { + width: 20px; + text-align: center; + } .dashboard-sidebar .nav > li > a:hover, .dashboard-sidebar .nav > li > a:focus { padding-left: 19px; @@ -364,7 +376,7 @@ width: 233px !important; } } - + @media (min-width: 1360px) { .container { padding-left: 3% !important; @@ -390,2097 +402,2255 @@ } </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'; - } - }; + <!-- 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, + update_always: false, + 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'; + }, + + genHash: function() { + var hash = urlOptions.hash; + + if(urlOptions.pan_and_zoom === true) { + hash += ';after=' + urlOptions.after.toString() + + ';before=' + urlOptions.before.toString(); + } - function netdataPanAndZoomCallback(status, after, before) { - urlOptions.pan_and_zoom = status; - urlOptions.after = after; - urlOptions.before = before; - netdataHashUpdate(); - } + if(urlOptions.theme !== null) + hash += ';theme=' + urlOptions.theme.toString(); - function netdataHashUpdate() { - history.replaceState(null, '', netdataHash()); - } + if(urlOptions.help !== null) + hash += ';help=' + urlOptions.help.toString(); - function netdataHash() { - var hash = urlOptions.hash; + if(urlOptions.update_always === true) + hash += ';update_always=true'; - if(urlOptions.pan_and_zoom === true) { - hash += ';after=' + urlOptions.after.toString() + - ';before=' + urlOptions.before.toString(); - } + return hash; + }, - if(urlOptions.theme !== null) - hash += ';theme=' + urlOptions.theme.toString(); + parseHash: function() { + 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]; + } + } - if(urlOptions.help !== null) - hash += ';help=' + urlOptions.help.toString(); + var booleans = [ 'nowelcome', 'show_alarms', 'pan_and_zoom', 'update_always' ]; + 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; + } - return hash; - } + if(urlOptions.before > 0 && urlOptions.after > 0) { + urlOptions.pan_and_zoom = true; + urlOptions.nowelcome = true; + } + else + urlOptions.pan_and_zoom = false; - 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]; - } - } + // console.log(urlOptions); + }, - 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; - } + hashUpdate: function() { + history.replaceState(null, '', urlOptions.genHash()); + }, - if(urlOptions.before > 0 && urlOptions.after > 0) { - urlOptions.pan_and_zoom = true; - urlOptions.nowelcome = true; - } - else - urlOptions.pan_and_zoom = false; + netdataPanAndZoomCallback: function(status, after, before) { + urlOptions.pan_and_zoom = status; + urlOptions.after = after; + urlOptions.before = before; + urlOptions.hashUpdate(); + } - // console.log(urlOptions); - } + }; - netdataHashParse(); + urlOptions.parseHash(); - // -------------------------------------------------------------------- - // check options that should be processed before loading netdata.js - - function loadLocalStorage(name) { - var ret = null; + // -------------------------------------------------------------------- + // check options that should be processed before loading netdata.js - try { - if(typeof Storage !== "undefined" && typeof localStorage === 'object') - ret = localStorage.getItem(name); - } - catch(error) { - ; - } + function loadLocalStorage(name) { + var ret = null; - if(typeof ret === 'undefined' || ret === null) - return null; + try { + if(typeof Storage !== "undefined" && typeof localStorage === 'object') + ret = localStorage.getItem(name); + } + catch(error) { + ; + } - // console.log('loaded: ' + name.toString() + ' = ' + ret.toString()); + if(typeof ret === 'undefined' || ret === null) + return null; - return ret; - } + // console.log('loaded: ' + name.toString() + ' = ' + ret.toString()); - 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; + 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; } - catch(error) { - ; + + function setTheme(theme) { + if(theme === netdataTheme) return false; + return saveLocalStorage('netdataTheme', theme); } - return false; - } + var netdataTheme = getTheme('slate'); + var netdataShowHelp = true; - function getTheme(def) { - var ret = loadLocalStorage('netdataTheme'); - if(typeof ret === 'undefined' || ret === null || ret === 'undefined') - return def; + if(urlOptions.theme !== null) { + setTheme(urlOptions.theme); + netdataTheme = urlOptions.theme; + } else - return ret; - } + urlOptions.theme = netdataTheme; - function setTheme(theme) { - if(theme === netdataTheme) return false; - return saveLocalStorage('netdataTheme', theme); - } + if(urlOptions.help !== null) { + saveLocalStorage('options.show_help', urlOptions.help); + netdataShowHelp = urlOptions.help; + } + else { + urlOptions.help = loadLocalStorage('options.show_help'); + } - var netdataTheme = getTheme('slate'); - var netdataShowHelp = true; + // -------------------------------------------------------------------- + // registry call back to render my-netdata menu - if(urlOptions.theme !== null) { - setTheme(urlOptions.theme); - netdataTheme = urlOptions.theme; - } - else - urlOptions.theme = netdataTheme; + var netdataRegistryCallback = function(machines_array) { + var el = ''; + var a1 = ''; + var found = 0; - if(urlOptions.help !== null) { - saveLocalStorage('options.show_help', urlOptions.help); - netdataShowHelp = urlOptions.help; - } - else { - urlOptions.help = loadLocalStorage('options.show_help'); - } + 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"); + } + } - // -------------------------------------------------------------------- - // registry call back to render my-netdata menu + if(machines_array) { + saveLocalStorage("registryCallback", JSON.stringify(machines_array)); - var netdataRegistryCallback = function(machines_array) { - var el = ''; - var a1 = ''; - var found = 0; + var machines = machines_array.sort(function (a, b) { + if (a.name > b.name) return -1; + if (a.name < b.name) return 1; + return 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"); + 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(machines_array) { - saveLocalStorage("registryCallback", JSON.stringify(machines_array)); + 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>'; + } - var machines = machines_array.sort(function (a, b) { - if (a.name > b.name) return -1; - if (a.name < b.name) return 1; - return 0; - }); + el += '<li role="separator" class="divider"></li>'; + a1 += '<li role="separator" class="divider"></li>'; - 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>'; + 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; // FIXME + 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) { + ; } - } - 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>'; + return this_is_demo; } - 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>' + function netdataURL(url) { + if(typeof url === 'undefined') + url = document.location.toString(); - document.getElementById('mynetdata_servers').innerHTML = el; - document.getElementById('mynetdata_servers2').innerHTML = el; - document.getElementById('mynetdata_actions1').innerHTML = a1; + if(url.indexOf('#') !== -1) + url = url.substring(0, url.indexOf('#')); - gotoServerInit(); - }; + var hash = urlOptions.genHash(); - var this_is_demo = null; - function isdemo() { - if(this_is_demo !== null) return this_is_demo; - this_is_demo = false; + // console.log('netdataURL: ' + url + hash); - 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 url + hash; } - return this_is_demo; - } + function netdataReload(url) { + var t = netdataURL(url); + // console.log('netdataReload: ' + t); + document.location = t; - function netdataURL(url) { - if(typeof url === 'undefined') - url = document.location.toString(); + // since we play with hash + // this is needed to reload the page + location.reload(); + } - if(url.indexOf('#') !== -1) - url = url.substring(0, url.indexOf('#')); + var gotoServerValidateRemaining = 0; + var gotoServerMiddleClick = false; + var gotoServerStop = false; + function gotoServerValidateUrl(id, guid, url) { + var penaldy = 0; + var error = 'failed'; - var hash = netdataHash(); + 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; - // console.log('netdataURL: ' + url + hash); + else if(document.location.toString().startsWith('https://') && url.toString().startsWith('http://')) + error = 'can\'t check'; - return url + hash; - } + var finalURL = netdataURL(url); - function netdataReload(url) { - var t = netdataURL(url); - // console.log('netdataReload: ' + t); - document.location = t; + 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>'; - // since we play with hash - // this is needed to reload the page - location.reload(); - } + 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"; - var gotoServerValidateRemaining = 0; - var gotoServerMiddleClick = false; - var gotoServerStop = false; - function gotoServerValidateUrl(id, guid, url) { - var penaldy = 0; - var error = 'failed'; + if(!gotoServerStop) { + gotoServerStop = true; - 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; + 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'; - else if(document.location.toString().startsWith('https://') && url.toString().startsWith('http://')) - error = 'can\'t check'; - - var finalURL = netdataURL(url); + 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); + } - 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>'; + function gotoServerModalHandler(guid) { + // console.log('goto server: ' + guid); - 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"; + gotoServerStop = false; + var checked = {}; + var len = NETDATA.registry.machines[guid].alternate_urls.length; + var count = 0; - if(!gotoServerStop) { - gotoServerStop = true; + document.getElementById('gotoServerResponse').innerHTML = ''; + document.getElementById('gotoServerList').innerHTML = ''; + document.getElementById('gotoServerName').innerHTML = NETDATA.registry.machines[guid].name; + $('#gotoServerModal').modal('show'); - 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; + 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 { - 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>'; - } + gotoServerMiddleClick = false; } + + return true; }); - }, (id * 50) + penaldy); - } + } - function gotoServerModalHandler(guid) { - // console.log('goto server: ' + guid); + function switchRegistryModalHandler() { + document.getElementById('switchRegistryPersonGUID').value = NETDATA.registry.person_guid; + document.getElementById('switchRegistryURL').innerHTML = NETDATA.registry.server; + document.getElementById('switchRegistryResponse').innerHTML = ''; + $('#switchRegistryModal').modal('show'); + } - gotoServerStop = false; - var checked = {}; - var len = NETDATA.registry.machines[guid].alternate_urls.length; - var count = 0; + function notifyForSwitchRegistry() { + var n = document.getElementById('switchRegistryPersonGUID').value; - document.getElementById('gotoServerResponse').innerHTML = ''; - document.getElementById('gotoServerList').innerHTML = ''; - document.getElementById('gotoServerName').innerHTML = NETDATA.registry.machines[guid].name; - $('#gotoServerModal').modal('show'); + 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>"; + } - gotoServerValidateRemaining = len; - while(len--) { - var url = NETDATA.registry.machines[guid].alternate_urls[len]; - checked[url] = true; - gotoServerValidateUrl(count++, guid, url); + 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'); } - 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); - } + 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>"; } }); } - }, 2000); - return false; - } + } - function gotoServerInit() { - $(".registry_link").on('click', function(e) { - if(e.which === 2) { - e.preventDefault(); - gotoServerMiddleClick = true; - } - else { - gotoServerMiddleClick = false; - } + 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, + }; - return true; - }); - } + // generate a sparkline + // used in the documentation + function sparkline(chart, dimension, units) { + var key = chart + '.' + dimension; - function switchRegistryModalHandler() { - document.getElementById('switchRegistryPersonGUID').value = NETDATA.registry.person_guid; - document.getElementById('switchRegistryURL').innerHTML = NETDATA.registry.server; - document.getElementById('switchRegistryResponse').innerHTML = ''; - $('#switchRegistryModal').modal('show'); - } + if(typeof units === 'undefined') + units = ''; - function notifyForSwitchRegistry() { - var n = document.getElementById('switchRegistryPersonGUID').value; + if(typeof options.sparklines_registry[key] === 'undefined') + options.sparklines_registry[key] = { count: 1 }; + else + options.sparklines_registry[key].count++; - 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>"; - } + key = key + '.' + options.sparklines_registry[key].count; - 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'); - } + 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 + ')'; - 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>"; - } - }); + return h; } - } - 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++; + function chartsPerRow(total) { + if(options.chartsPerRow === 0) { + width = Math.floor(total / options.chartsMinWidth); + if(width === 0) width = 1; + return width; + } + else return options.chartsPerRow; + } - key = key + '.' + options.sparklines_registry[key].count; + 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; + } - 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 + ')'; + function sortObjectByPriority(object) { + var idx = {}; + var sorted = new Array(); - return h; - } + for(var i in object) { + if(typeof idx[i] === 'undefined') { + idx[i] = object[i]; + sorted.push(i); + } + } - function chartsPerRow(total) { - if(options.chartsPerRow === 0) { - width = Math.floor(total / options.chartsMinWidth); - if(width === 0) width = 1; - return width; + 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; } - 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(); + // ---------------------------------------------------------------------------- + // scroll to a section, without changing the browser history - for(var i in object) { - if(typeof idx[i] === 'undefined') { - idx[i] = object[i]; - sorted.push(i); + function scrollToId(hash) { + if(hash && hash != '' && document.getElementById(hash) !== null) { + 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; } - 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; - }); + // ---------------------------------------------------------------------------- + + 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; + }, - return sorted; - } + 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, ' '); + }, - // ---------------------------------------------------------------------------- - // scroll to a section, without changing the browser history + 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(); - function scrollToId(hash) { - if(hash && hash != '') { - var offset = $('#' + hash).offset(); - if(typeof offset !== 'undefined') - $('html, body').animate({ scrollTop: offset.top }, 0); - } + return netdataDashboard.anyAttribute(netdataDashboard.menu, 'icon', chart.menu, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>'); + }, - // we must return false to prevent the default action - return false; - } + menuInfo: function(menu) { + return netdataDashboard.anyAttribute(netdataDashboard.menu, 'info', menu, null); + }, - // ---------------------------------------------------------------------------- - - 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; - }, + menuHeight: function(menu, relative) { + return netdataDashboard.anyAttribute(netdataDashboard.menu, 'height', menu, 1.0) * relative; + }, - 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, ' '); - } + 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 ''; + }, - return (netdataDashboard.anyAttribute(netdataDashboard.menu, 'title', chart.menu, chart.menu)).toString().replace(/_/g, ' '); - }, + contextValueRange: function(id) { + if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].valueRange !== 'undefined') + return netdataDashboard.context[id].valueRange; + else + return '[null, null]'; + }, - 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(); + 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; + } + }; - 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); - }, + // enrich the data structure returned by netdata + // to reflect our menu system and content + function enrichChartData(chart) { + var tmp = chart.type.split('_')[0]; - menuHeight: function(menu, relative) { - return netdataDashboard.anyAttribute(netdataDashboard.menu, 'height', menu, 1.0) * relative; - }, + switch(tmp) { + case 'ap': + case 'net': + case 'disk': + chart.menu = tmp; + break; - 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 ''; - }, + 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 'dovecot': + case 'hddtemp': + case 'ipfs': + case 'memcached': + case 'mysql': + case 'named': + case 'nginx': + case 'nut': + case 'phpfpm': + case 'postfix': + case 'postgres': + case 'redis': + case 'retroshare': + case 'smawebbox': + case 'snmp': + case 'squid': + 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); + } - 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--; - // increase the priority of IFB devices - // to have inbound appear before outbound - if(chart.id.match(/.*-ifb$/)) - chart.priority--; + break; - break; + default: + chart.menu = chart.type; + break; + } - default: - chart.menu = chart.type; - break; + chart.submenu = chart.family; } - 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="used"' + + ' data-append-options="percentage"' + + ' data-chart-library="easypiechart"' + + ' data-title="Used 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>'; + } - // ---------------------------------------------------------------------------- - - 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.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="used|buffers|active|wired"' // active and wired are FreeBSD stats + + ' data-append-options="percentage"' + + ' data-chart-library="easypiechart"' + + ' data-title="Used 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; } - 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++; + 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; } - 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); + 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-dygraph-valuerange="' + netdataDashboard.contextValueRange(chart.context) + '"' + + ' 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>'; } - head += '</div>'; - shtml += head + chtml + '</div>'; + mhead += '</div>'; + sidebar += '</ul></li>'; + html += mhead + shtml + '</div></div><hr role="separator"/>'; } - mhead += '</div>'; - sidebar += '</ul></li>'; - html += mhead + shtml + '</div></div><hr role="separator"/>'; + sidebar += '<li class="" style="padding-top:15px;"><a href="https://github.com/firehol/netdata/wiki/Add-more-charts-to-netdata" target="_blank"><i class="fa fa-plus" aria-hidden="true"></i> add more charts</a></li>'; + sidebar += '<li class=""><a href="https://github.com/firehol/netdata/wiki/Add-more-alarms-to-netdata" target="_blank"><i class="fa fa-plus" aria-hidden="true"></i> add more alarms</a></li>'; + sidebar += '<li class="" style="margin:20px;color:#666;"><small>netdata on <b>' + data.hostname.toString() + '</b>, collects every ' + ((data.update_every == 1)?'second':data.update_every.toString() + ' seconds') + ' <b>' + data.dimensions_count.toLocaleString() + '</b> metrics, presented as <b>' + data.charts_count.toLocaleString() + '</b> charts and monitored by <b>' + data.alarms_count.toLocaleString() + '</b> alarms, using ' + Math.round(data.rrd_memory_bytes / 1024 / 1024).toLocaleString() + ' MB of memory for ' + Math.round(data.history / (3600/data.update_every)).toLocaleString() + ' ' + ((data.history == (3600/data.update_every))?'hour':'hours').toString() + ' of real-time history.</small></li>'; + sidebar += '</ul>'; + div.innerHTML = html; + document.getElementById('sidebar').innerHTML = sidebar; + finalizePage(); } - 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) + }; + } - 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]); } - 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) - }; + // 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); + } + } } - 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; + renderPage(menus, data); + } - // index the chart in the menu/submenu - menus[charts[c].menu].submenus[charts[c].submenu].charts.push(charts[c]); + // ---------------------------------------------------------------------------- + + 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(); + }) } - // 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); - } + 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(); } - 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(); - }) - } + 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.'; - 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(); - } + NETDATA.alarms.get('all', function(data) { + options.alarm_families = new Array(); - 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.'; + alarmsCallback(data); - NETDATA.alarms.get('all', function(data) { - options.alarm_families = new Array(); + if(data === null) { + document.getElementById('alarms_active').innerHTML = + document.getElementById('alarms_all').innerHTML = + document.getElementById('alarms_log').innerHTML = + 'failed to load alarm data!'; + return; + } - alarmsCallback(data); + function alarmid4human(id) { + if(id === 0) + return '-'; - 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 = ' '; + return id.toString(); + } - var t = new Date(timestamp * 1000); - var now = new Date(); + function timestamp4human(timestamp, space) { + if(timestamp === 0) + return '-'; - if(t.toDateString() == now.toDateString()) - return t.toLocaleTimeString(); + if(typeof space === 'undefined') + space = ' '; - return t.toLocaleDateString() + space + t.toLocaleTimeString(); - } + var t = new Date(timestamp * 1000); + var now = new Date(); - 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(t.toDateString() == now.toDateString()) + return t.toLocaleTimeString(); - 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]; - } + return t.toLocaleDateString() + space + t.toLocaleTimeString(); } - if(typeof seconds === 'string') - seconds = parseInt(seconds); + 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(seconds === 0) - return options.now; + 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]; + } + } - var suffix = ''; - if(seconds < 0) { - seconds = -seconds; - if(options.negative_suffix !== '') suffix = options.space + options.negative_suffix; - } + if(typeof seconds === 'string') + seconds = parseInt(seconds); - var hours = Math.floor(seconds / 3600); - seconds -= (hours * 3600); + if(seconds === 0) + return options.now; - var minutes = Math.floor(seconds / 60); - seconds -= (minutes * 60); + var suffix = ''; + if(seconds < 0) { + seconds = -seconds; + if(options.negative_suffix !== '') suffix = options.space + options.negative_suffix; + } - var txt = ''; - - if(hours > 1) txt += hours.toString() + options.space + options.hours; - else if(hours === 1) txt += hours.toString() + options.space + options.hour; + var hours = Math.floor(seconds / 3600); + seconds -= (hours * 3600); - 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; + var minutes = Math.floor(seconds / 60); + seconds -= (minutes * 60); - if(minutes > 1) txt += minutes.toString() + options.space + options.minutes; - else if(minutes === 1) txt += minutes.toString() + options.space + options.minute; + var txt = ''; - if((minutes > 0 || minutes > 0) && seconds > 0) - txt += options.space + options.and + options.space; + if(hours > 1) txt += hours.toString() + options.space + options.hours; + else if(hours === 1) txt += hours.toString() + options.space + options.hour; - 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; + 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; - return txt + suffix; - } + if(minutes > 1) txt += minutes.toString() + options.space + options.minutes; + else if(minutes === 1) txt += minutes.toString() + options.space + options.minute; - function alarm_lookup_explain(alarm, chart) { - var dimensions = ' of all values '; + if((minutes > 0 || minutes > 0) && seconds > 0) + txt += options.space + options.and + options.space; - if(chart.dimensions.length > 1) - dimensions = ' of the sum of all dimensions '; + 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; - 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 txt + suffix; } - 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_lookup_explain(alarm, chart) { + var dimensions = ' of all values '; - function alarm_to_html(alarm, full) { - var chart = options.data.charts[alarm.chart]; + if(chart.dimensions.length > 1) + dimensions = ' of the sum of all dimensions '; - 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(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> '; + } - 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>'):''); + 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>'):'') + + '.'; } - 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: '' }); + function alarm_to_html(alarm, full) { + var chart = options.data.charts[alarm.chart]; + var has_alarm = ((typeof alarm.warn !== 'undefined' || typeof alarm.crit !== 'undefined')?true:false); + + var role_href = ((has_alarm === true)?('<br/> <br/>role: <b>' + alarm.recipient + '</b><br/> <br/><b><i class="fa fa-line-chart" aria-hidden="true"></i></b><small> <a href="#" onClick="NETDATA.alarms.scrollToChart(\'' + alarm.chart + '\'); $(\'#alarmsModal\').modal(\'hide\'); return false;">jump to chart</a></small>'):(' ')); + + var html = '<tr><td class="text-center" style="vertical-align:middle" width="40%"><b>' + alarm.chart + '</b><br/> <br/><embed src="' + NETDATA.alarms.server + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto" type="image/svg+xml" height="20"/><br/> <br/><span style="font-size: 18px">' + alarm.info + '</span>' + role_href + '</td>' + + '<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>'):''); } - else { - delay = '<small><br/>hysteresis '; - if(alarm.delay_up_duration > 0) { - delay += 'on escalation <code>' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' }) + '</code>, '; + + 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: '' }); } - if(alarm.delay_down_duration > 0) { - delay += 'on recovery <code>' + seconds4human(alarm.delay_down_duration, { negative_suffix: '' }) + '</code>, '; + 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>'; } - 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; - } + html += '<tr><td width="10%" style="text-align:right">check every</td><td>' + seconds4human(alarm.update_every, { negative_suffix: '' }) + '</td></tr>' + + ((has_alarm === true)?('<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span>' + delay + '</td></tr>'):'') + + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>' + + '</table></td></tr>'; - 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); + return html; } - 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]; + 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>'; - // 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 }; + $('#alarm_all_' + id.toString()).html(html); } - 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]); - } + // find the proper family of each alarm + var now = Date.now(); + 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; + if(chart.priority < families[family].priority) + families[family].priority = chart.priority; - families[family].arr.unshift(alarm); - } + 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; - }); + // 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 = ''; - } + 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() + '">'; + 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]; + options.alarm_families[fc] = families[family]; - fc++; + 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>'; + 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_active++; - active += alarm_to_html(alarm, true); - } - count_all++; + count_all++; + } } - } - active += "</table>"; - if(families_sorted.length > 0) all += "</div></div></div>"; - all += "</div>"; + 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_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; + 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; + document.getElementById('alarms_active').innerHTML = active; + document.getElementById('alarms_all').innerHTML = all; - if(families_sorted.length > 0) alarm_family_show(0); + 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(''); - }); + // 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 + 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' }, - { - 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 + 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 {}; }, - { - field: 'name', - title: 'Alarm', - titleTooltip: 'The alarm name that generated this event', - formatter: function(value, row, index) { - return value.toString().replace(/_/g, ' '); + 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', + formatter: function(value, row, index) { return timestamp4human(value, ' '); }, + align: 'center', + valign: 'middle', + switchable: false, + sortable: true }, - 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(); + { + field: 'hostname', + title: 'Host', + valign: 'middle', + titleTooltip: 'The host that generated this event', + align: 'center', + valign: 'middle', + visible: false, + sortable: true }, - 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 - } - ] + { + field: 'unique_id', + title: 'Unique ID', + titleTooltip: 'The host unique ID for this event', + formatter: function(value, row, index) { return alarmid4human(value); }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'alarm_id', + title: 'Alarm ID', + titleTooltip: 'The ID of the alarm that generated this event', + formatter: function(value, row, index) { return alarmid4human(value); }, + align: 'center', + 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', + formatter: function(value, row, index) { return alarmid4human(value); }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'chart', + title: 'Chart', + titleTooltip: 'The chart the alarm is attached to', + align: 'center', + valign: 'middle', + switchable: false, + sortable: true + }, + { + field: 'family', + title: 'Family', + titleTooltip: 'The family of the chart the alarm is attached to', + align: 'center', + 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, ' '); + }, + align: 'center', + valign: 'middle', + switchable: false, + sortable: true + }, + { + field: 'old_value', + title: 'Old Value', + titleTooltip: 'The value of the alarm, just before this event', + formatter: function(value, row, index) { + return ((value !== null)?Math.round(value * 100) / 100:'NaN').toString(); + }, + align: 'center', + 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.round(value * 100) / 100:'NaN').toString(); + }, + align: 'right', + valign: 'middle', + sortable: true + }, + { + field: 'units', + title: 'Units', + titleTooltip: 'The units of the value of the alarm', + align: 'left', + valign: 'middle', + sortable: true + }, + { + field: 'old_status', + title: 'Old Status', + titleTooltip: 'The status of the alarm, just before this event', + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'status', + title: 'Status', + titleTooltip: 'The status of the alarm, that was set due to this event', + align: 'center', + 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' }); }, + align: 'center', + 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' }); }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'recipient', + title: 'Recipient', + titleTooltip: 'The recipient of this event', + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'processed', + title: 'Processed Status', + titleTooltip: 'True when this event is processed', + formatter: function(value, row, index) { + if(value === true) + return 'DONE'; + else + return 'PENDING'; + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'updated', + title: 'Updated Status', + titleTooltip: 'True when this event has been updated by another event', + formatter: function(value, row, index) { + if(value === true) + return 'UPDATED'; + else + return 'CURRENT'; + }, + align: 'center', + 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', + formatter: function(value, row, index) { return alarmid4human(value); }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'updates_id', + title: 'Updates ID', + titleTooltip: 'The unique ID of the event obsoleted because of this event', + formatter: function(value, row, index) { return alarmid4human(value); }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'exec', + title: 'Script', + titleTooltip: 'The script to handle the event notification', + align: 'center', + 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, ' '); }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'exec_code', + title: 'Script Return Value', + titleTooltip: 'The return code of the script', + formatter: function(value, row, index) { + if(value === 0) + return 'OK (returned 0)'; + else + return 'FAILED (with code ' + value.toString() + ')'; + }, + align: 'center', + 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' }); }, + align: 'center', + 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, ' '); }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'info', + title: 'Description', + titleTooltip: 'A short description of the alarm', + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'source', + title: 'Alarm Source', + titleTooltip: 'The source of configuration of the alarm', + align: 'center', + valign: 'middle', + visible: false, + sortable: true + } + ] + }); + // console.log($('#alarms_log_table').bootstrapTable('getOptions')); }); - // 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++; + 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 = ''; } - 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; + } - 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); } - - // render all charts - renderChartsAndMenu(data); - } + }); }); - }); - } + } - // ---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- - function versionLog(msg) { - document.getElementById('versionCheckLog').innerHTML = msg; - } + 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.'); + 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); - } - 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); + 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); }); - }); + } - return null; - } + function checkForUpdate(callback) { + getNetdataVersion(function(sha1) { + if(sha1 === null) callback(null, null); - function notifyForUpdate(force) { - versionLog('<p>checking for updates...</p>'); + getGithubLatestCommit(function(sha2) { + callback(sha1, sha2); + }); + }); - var now = new Date().getTime(); + return null; + } - if(typeof force === 'undefined' || force !== true) { - var last = loadLocalStorage('last_update_check'); + function notifyForUpdate(force) { + versionLog('<p>checking for updates...</p>'); - if(typeof last === 'string') - last = parseInt(last); - else - last = 0; + var now = Date.now(); - if(now - last < 3600000 * 8) { - // no need to check it - too soon - return; - } - } + if(typeof force === 'undefined' || force !== true) { + var last = loadLocalStorage('last_update_check'); - checkForUpdate(function(sha1, sha2) { - var save = false; + if(typeof last === 'string') + last = parseInt(last); + else + last = 0; - 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>'); + if(now - last < 3600000 * 8) { + // no need to check it - too soon + return; + } } - 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>'); + checkForUpdate(function(sha1, sha2) { + var save = false; - document.getElementById('update_badge').innerHTML = '!'; - } - - if(save) - saveLocalStorage('last_update_check', now.toString()); - }); - } + 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(); - // ---------------------------------------------------------------------------- - - 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 - }; + 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>'); - if (settings) { - $.extend(config, settings); - } + document.getElementById('update_badge').innerHTML = '!'; + } - if ($(this).data('jquery.shorten') && !config.force) { - return false; - } - $(this).data('jquery.shorten', true); + if(save) + saveLocalStorage('last_update_check', now.toString()); + }); + } - $(document).off("click", '.morelink'); + // ---------------------------------------------------------------------------- + + 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 + }; - $(document).on({ - click: function() { + if (settings) { + $.extend(config, settings); + } - 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(); - }); - } + if ($(this).data('jquery.shorten') && !config.force) { return false; } - }, '.morelink'); + $(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); - 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; - 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; - 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)); - // This could be "tag" or "/tag" - tagName = content.substring(i + 1, content.indexOf('>', i)); + // If its a closing tag + if (tagName[0] == '/') { - // 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!) + } - 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 + // 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 && 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 + 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 { - //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 + 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; } - break; } } } + c = $('<div/>').html(bag + '<span class="ellip">' + config.ellipsesText + '</span>').html(); + }else{ + c+=config.ellipsesText; } - 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 } + }); - var html = '<div class="shortcontent">' + c + - '</div><div class="allcontent">' + content + - '</div><span><a href="javascript://nop/" class="morelink">' + config.moreText + '</a></span>'; + }; + $(".chart-message").shorten(); + // ------------------------------------------------------------------------ + + // callback for us to track PanAndZoom operations + NETDATA.globalPanAndZoom.callback = urlOptions.netdataPanAndZoomCallback; + + // let it run (update the charts) + NETDATA.unpause(); - $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 + // 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 } }); - }; - $(".chart-message").shorten(); - // ------------------------------------------------------------------------ + /* 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'); + }); - // callback for us to track PanAndZoom operations - NETDATA.globalPanAndZoom.callback = netdataPanAndZoomCallback; + /* 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 + }); - // let it run (update the charts) - NETDATA.unpause(); + // 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); + urlOptions.hashUpdate(); + } + //else console.log('hash: not accepting ' + hash); + //} + //else console.log('el.find(): not found'); + }); - // check if we have to jump to a specific section - scrollToId(urlOptions.hash.replace('#','')); + document.getElementById('footer').style.display = 'block'; - 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); - } + var update_options_modal = function() { + // console.log('update_options_modal'); - /* 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'); - }); + var sync_option = function(option) { + var self = $('#' + option); - document.getElementById('footer').style.display = 'block'; + if(self.prop('checked') !== NETDATA.getOption(option)) { + // console.log('switching ' + option.toString()); + self.bootstrapToggle(NETDATA.getOption(option)?'on':'off'); + } + } - var update_options_modal = function() { - // console.log('update_options_modal'); + var theme_sync_option = function(option) { + var self = $('#' + option); - var sync_option = function(option) { - var self = $('#' + option); + self.bootstrapToggle(netdataTheme === 'slate'?'on':'off'); + } - if(self.prop('checked') !== NETDATA.getOption(option)) { - // console.log('switching ' + option.toString()); - self.bootstrapToggle(NETDATA.getOption(option)?'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() { + urlOptions.update_always = !$(this).prop('checked'); + urlOptions.hashUpdate(); + + NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always); + }); + $('#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'); + urlOptions.hashUpdate(); - var theme_sync_option = function(option) { - var self = $('#' + option); + NETDATA.setOption('show_help', urlOptions.help); + netdataReload(); + }); - self.bootstrapToggle(netdataTheme === 'slate'?'on':'off'); - } + // this has to be the last + // it reloads the page + $('#netdata_theme_control').change(function() { + urlOptions.theme = $(this).prop('checked')?'slate':'white'; + urlOptions.hashUpdate(); - 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(); - }); + if(setTheme(urlOptions.theme)) + netdataReload(); + }); - $('#updateModal').on('shown.bs.modal', function() { - notifyForUpdate(true); - }); + $('#updateModal').on('show.bs.modal', function() { + versionLog('checking, please wait...'); + }); - $('#alarmsModal').on('shown.bs.modal', function() { - NETDATA.pause(alarmsUpdateModal); - }); + $('#updateModal').on('shown.bs.modal', function() { + notifyForUpdate(true); + }); - $('#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) { + $('#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()) { + // do not to give errors on netdata demo servers for 60 seconds + NETDATA.options.current.retries_on_data_failures = 60; + + 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() { - $('#welcomeModal').modal(); - }, 1000); + (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); + + var sidebar = document.getElementById('sidebar'); + Ps.initialize(sidebar, { + wheelSpeed: 0.5, + wheelPropagation: true, + swipePropagation: true, + minScrollbarLength: null, + maxScrollbarLength: null, + useBothWheelAxes: false, + suppressScrollX: true, + suppressScrollY: false, + scrollXMarginOffset: 0, + scrollYMarginOffset: 0, + theme: 'default' + }); + Ps.update(sidebar); + + var registry = document.getElementById('myNetdataDropdownUL'); + Ps.initialize(registry, { + wheelSpeed: 1, + wheelPropagation: false, + swipePropagation: false, + minScrollbarLength: null, + maxScrollbarLength: null, + useBothWheelAxes: false, + suppressScrollX: true, + suppressScrollY: false, + scrollXMarginOffset: 0, + scrollYMarginOffset: 0, + theme: 'default' + }); + Ps.update(registry); - // 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'); + NETDATA.onresizeCallback = function() { + Ps.update(sidebar); + Ps.update(registry); + }; - ga('create', 'UA-64295674-3', 'auto'); - ga('send', 'pageview'); - }, 2000); + $('#myNetdataDropdownParent') + .on('show.bs.dropdown', function () { + NETDATA.pause(function() {}); + }) + .on('shown.bs.dropdown', function () { + Ps.update(registry); + }) + .on('hidden.bs.dropdown', function () { + NETDATA.unpause(); + }); + + // var netdataEnded = performance.now(); + // console.log('start up time: ' + (netdataEnded - netdataStarted).toString() + ' ms'); } - else notifyForUpdate(); - if(urlOptions.show_alarms === true) - setTimeout(function() { $('#alarmsModal').modal('show'); }, 1000); - } + function resetDashboardOptions() { + var help = NETDATA.options.current.show_help; - function resetDashboardOptions() { - var help = NETDATA.options.current.show_help; + NETDATA.resetOptions(); + if(setTheme('slate')) + netdataReload(); - NETDATA.resetOptions(); - if(setTheme('slate')) - netdataReload(); + if(help !== NETDATA.options.current.show_help) + 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; } + }); - // 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'; - } - } + NETDATA.requiredJs.push({ + url: NETDATA.serverDefault + 'lib/bootstrap-toggle-2.2.2.min.js', + isAlreadyLoaded: function() { return false; } + }); - // our entry point - var netdataCallback = initializeDynamicDashboard; + NETDATA.requiredJs.push({ + url: NETDATA.serverDefault + 'dashboard_info.js?v20170115-1', + async: false, + isAlreadyLoaded: function() { return false; } + }); -</script> + if(isdemo()) { + document.getElementById('masthead').style.display = 'block'; + } + else { + if(urlOptions.update_always === true) + NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always); + } + }; + + // our entry point + // var netdataStarted = performance.now(); + var netdataCallback = initializeDynamicDashboard; + </script> +</head> <body data-spy="scroll" data-target="#sidebar"> <div id="loadOverlay" class="loadOverlay" style="background-color: #888; color: #888;"> @@ -2494,9 +2664,9 @@ <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"> + <li class="dropdown" id="myNetdataDropdownParent"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a> + <ul class="dropdown-menu scrollable-menu inpagemenu multi-column columns-2" role="menu" id="myNetdataDropdownUL"> <div class="row"> <div class="col-sm-6" style="width: 85%; padding-right: 0;"> <ul id="mynetdata_servers" class="multi-column-dropdown"> @@ -2524,31 +2694,21 @@ </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="#alarmsModal" title="alarms"><i class="fa fa-bell"></i> <span class="hidden-sm">Alarms </span><span id="alarms_count_badge" class="badge"></span></a></li> <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" id="updateButton"><a href="#" class="btn" data-toggle="modal" data-target="#updateModal" title="check for update"><i class="fa fa-cloud-download"></i> <span class="hidden-sm hidden-md">Update </span><span id="update_badge" class="badge"></span></a></li> + <li><a href="https://github.com/firehol/netdata/wiki" class="btn" target="_blank" title="netdata on github"><i class="fa fa-github"></i></a></li> + <li><a href="https://twitter.com/linuxnetdata" class="btn" target="_blank" title="netdata on twitter"><i class="fa fa-twitter" aria-hidden="true"></i></a></li> + <li><a href="https://www.facebook.com/linuxnetdata/" class="btn" target="_blank" title="netdata on facebook"><i class="fa fa-facebook-official" aria-hidden="true"></i></a></li> <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> + <a href="#" class="dropdown-toggle" data-toggle="dropdown">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> @@ -2584,7 +2744,7 @@ <div class="charts-body" role="main"> <div id="charts_div"></div> </div> - <div class="sidebar-body hidden-xs hidden-sm" role="complementary"> + <div class="sidebar-body hidden-xs hidden-sm" id="sidebar-body" role="complementary"> <nav class="dashboard-sidebar hidden-print hidden-xs hidden-sm" id="sidebar" role="menu"></nav> </div> </div> @@ -2595,7 +2755,7 @@ <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/> + <i class="fa fa-copyright"></i> Copyright 2016-2017, <a href="mailto:costa@tsaousis.gr">Costa Tsaousis</a>.<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"> @@ -2620,8 +2780,8 @@ <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://github.com/noraesae/perfect-scrollbar" target="_blank">perfect-scrollbar</a>, + <i class="fa fa-copyright"></i> Copyright 2016, Hyunje Alex Jun and other contributors, <a href="https://github.com/noraesae/perfect-scrollbar/blob/master/LICENSE" target="_blank">MIT License</a> <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> @@ -2645,28 +2805,43 @@ <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> + <h4 class="modal-title" id="welcomeModalLabel">Welcome to the world of netdata</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 class="p"> + <div style="width: 100%; text-align: center; padding-top: 10px; padding-bottom: 10px; font-size: 18px;"> + if there is a metric for something, we want it visualised<br/> + and we want this visualisation to be <strong>real-time</strong>, <strong>efficient</strong> and <strong>awesome</strong> </div> + </div> + <div class="p"> + <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> + is a new way to monitor your systems and applications, to get <strong>real-time insights</strong> + of what is really happening and what affects performance. + It is carefully optimised to be a real-time system, without interfering in any way, + to the core function of your systems. + </div> + <div class="p"> + <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> + has been designed to monitor <strong>massive amounts of metrics, per server, per second</strong>. + When installed, it might come up with 1k to 3k metrics, but we have been testing it with 100k + metrics, all collected per second, and still the cpu utilisation remained negligible. + <br/> + We have also tried to give each metric, a meaning, a context. + We have grouped and categorized all metrics into meaningful charts, providing a + better understanding of the underlying technologies and mechanisms. + </div> + <div class="p"> + <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> is free, + open-source software. If you decide to use it, + <strong><a href="https://github.com/firehol/netdata/wiki/a-github-star-is-important" target="_blank">it is important to give netdata a star at GitHub</a></strong>. + </div> + <div class="p"> + Enjoy real-time performance monitoring! + </div> + <div class="p"> + Costa Tsaousis + </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> @@ -2727,7 +2902,7 @@ </div> <hr/> <div class="p"> - <h4>SHIFT + Mouse Wheel <small>(does not work on firefox and IE/Edge)</small></h4> + <h4>SHIFT + Mouse Wheel</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. @@ -2888,23 +3063,13 @@ <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> <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/> + <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> <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/> @@ -2983,6 +3148,17 @@ <br/> <div style="padding: 10px;"></div> <div id="versionCheckLog">Not checked yet. Please press the Check Now button.</div> + <div> + <hr/> + </div> + <div> + For progress reports and key netdata updates: <strong><a href="https://twitter.com/linuxnetdata" target="_blank">follow netdata on <i class="fa fa-twitter" aria-hidden="true"></i> twitter</a></strong>. + <br/> + <small> + You can also <a href="https://www.facebook.com/linuxnetdata/" target="_blank">follow netdata on <i class="fa fa-facebook" aria-hidden="true"></i> facebook</a>, + or <a href="https://github.com/firehol/netdata" target="_blank">watch netdata on <i class="fa fa-github" aria-hidden="true"></i> github</a>. + </small> + </div> </div> <div class="modal-footer"> <a href="#" onclick="notifyForUpdate(true); return false;" type="button" class="btn btn-default">Check Now</a> @@ -3033,9 +3209,9 @@ <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> + <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> @@ -3083,4 +3259,4 @@ </div> </body> </html> -<script type="text/javascript" src="dashboard.js?v20161004-1"></script> +<script type="text/javascript" src="dashboard.js?v20170118-11"></script> |