diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2018-12-28 14:38:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2018-12-28 14:38:58 +0000 |
commit | fa4ece01aed54c9a146af868be0d3db611ded229 (patch) | |
tree | 319cffc5f6c2abd7cce514383716153469fc6295 /web/gui/index.html | |
parent | New upstream version 1.11.0+dfsg (diff) | |
download | netdata-fa4ece01aed54c9a146af868be0d3db611ded229.tar.xz netdata-fa4ece01aed54c9a146af868be0d3db611ded229.zip |
New upstream version 1.11.1+dfsgupstream/1.11.1+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'web/gui/index.html')
-rw-r--r-- | web/gui/index.html | 4614 |
1 files changed, 43 insertions, 4571 deletions
diff --git a/web/gui/index.html b/web/gui/index.html index 0a01b1df9..c6d460bf5 100644 --- a/web/gui/index.html +++ b/web/gui/index.html @@ -13,24 +13,27 @@ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <meta name="author" content="costa@tsaousis.gr"> - <!-- <link rel="shortcut icon" href="images/seo-performance-multi-size.ico"> --> - - <!-- <link rel="apple-touch-icon" href="images/seo-performance-72.png"> --> - <!-- <link rel="apple-touch-icon" sizes="72x72" href="images/seo-performance-72.png"> --> - <!-- <link rel="apple-touch-icon" sizes="114x114" href="images/seo-performance-114.png"> --> - - <!-- <link rel="icon" type="image/png" sizes="512x512" href="images/seo-performance-512.png"> --> - <!-- <link rel="icon" type="image/png" sizes="256x256" href="images/seo-performance-256.png"> --> - <!-- <link rel="icon" type="image/png" sizes="128x128" href="images/seo-performance-128.png"> --> - <!-- <link rel="icon" type="image/png" sizes="64x64" href="images/seo-performance-64.png"> --> - <!-- <link rel="icon" type="image/png" sizes="48x48" href="images/seo-performance-48.png"> --> - <!-- <link rel="icon" type="image/png" sizes="24x24" href="images/seo-performance-24.png"> --> - <!-- <link rel="icon" type="image/png" sizes="16x16" href="images/seo-performance-16.png"> --> - <!-- <link rel="icon" type="image/png" sizes="32x32" href="images/seo-performance-32.png"> --> - - <link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACNklEQVRYhcXXv2tUQRAH8M+FEIJISBHCIWIhIQSUILERi4AiiqCggiIiomAjlhaC4j+ghYWISgqNohZaCBZBC8Ei8QdEUCutFBsxCBqDYkgci/cunkfuJffjJQPD8mZm5/vd2WV2HzlJ0Bs8CvrywsgCHwy+BpGOg0sJfjj4nYKX9FdwKG9gwZlgtgK8pLOpPxfw1mCoCnClDgWtzQTvCEYWCV7SkWAlFBoEb8dlDKBF8t2bMWUSH/AHr3CiEfz5CPUusPJLkRCdk5ZqyeqUrQv4R7E5TwK7M3zTeIKduRAIitiWEfIY69GdCwGcRFuG/xqONRkzkaA7+J5x+MaDtWmHvJ4HgeEM8Nn0bridfv9HoOFyBAdwJCPkqqTzHWwUaz7wgeBHxupfBKuCj2W25mxBsCGYyAB/FxTT27HcPlyep64tCLbjKbqqhLzBlgKfF8pVE4FgRXABI+ioEnYfOyzcFWsCbg+OV+xlpU4ER4O+4HVwL51b3xYEXcGu4Ao+YQhr5gmdxHmsQyfG0b/YxbWmLfRWmnxa0s06VbTMCpnBS9zFzQKTwR5cXCzwHIE02Sl8wSZsRI/kgLVJqjSd+t9LVjiG1diPszhdK3A5gR48k5zYMTwscC59sfT799CYKvA8EttbSeXgTr3gJQKl91kR+yTlvyG5uUbLYh9gb+ovltkb6qYtNSRo3kOygsBSzGlKsubf43USWLYK5CLLXoFWyU/CtzLbVDpW2n+m40yN9ukqdvAX9ac/EIgOapcAAAAASUVORK5CYII="> - - <link rel="mask-icon" href="images/netdata.svg" color="red" /> + <link rel="stylesheet" type="text/css" href="main.css?v=2"> + + <link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACyklEQVRYhcWXz0sUYRjHP8+wLItImEhnEfEgEVJk+56CbCECQWezOkTQTTp6kejgKUSoEAoK/wAhaaeDBkLoIahZIWIJo0U8hHQJJBYJERGfDrOju7PjuO5u6/c0PM/7zvfzvvP+eEaoVu6wBZIA3cW82wtvY7cD1xEWSTpb1bxWjm2RtbtQxoF7iLSA7gO/UL4A74G3mBIzNz0Peg1hFmUK46zXBuDaCYQJlDFE4ke/QreAZyhPMc42rt2PyEoxt4cyDUxgnO3qAVy7C8gg0hdFHwBZA0ZIOt9w7e+I9B6mdBVhmGTlbFQCuPYFhA8g56o3P3D6CwyiDCIyFshtgqRIZnKlUStg3lW7OYC0AvPATkiuA9U3uOlEOEDWTgCZ2s3LIMbCU9ID3A8HUCZO9s2jGCRxdFIflDUF/EX3I3q1N0iq+8BZf+v6MzDeFHMAEQvoJpuOAwiu3Qr89g6ZJkm5CnoHeBwDbjTV3CPoRRhF+WQBA801B+AJiAUMWMDFptuLtBef+iygs+kAh+q0gDOnCNBmETyOmywLKJyifyEG/ATqPP+LUt0FZoAlIA6MgNyKqDo2YkAO6G+QeQrjfCyJzuHaoyCvjuiVs4q0jdBMwNyTcV6j+jm0h7BkAYuohpZLJ1TUQJYrIqo7KAtW8VaabQBA1GVWmROZwzgFfwtOoRpealevdGg0a8eAoUB0D9VJ8M8A46yDTNdlL9wmaz8MMX9RrIQOpfoS4+S9br7cdAvoCiLn6wLxFtwyQhxlKMQ8j3CJpFeml+9QN90N6iLSURfEkXD8AQwms+aHyo9hk1kHSaG6+Z/MU6XmlQAeRA7EoLraQPM83si/BlPhF5E3E1dQfY5S++5Q/9dMLwdH7uv4n1PX7gEeAXejy+0y4x2QOWASk8lHNT0e4AAk3QZ6E6+E68MrZNqK2QKwgXevLCEskHSqumX/AUXU5QBtOC5FAAAAAElFTkSuQmCC"> + + <!-- <link rel="apple-touch-icon" sizes="57x57" href="images/apple-icon-57x57.png"> + <link rel="apple-touch-icon" sizes="60x60" href="images/apple-icon-60x60.png"> + <link rel="apple-touch-icon" sizes="72x72" href="images/apple-icon-72x72.png"> + <link rel="apple-touch-icon" sizes="76x76" href="images/apple-icon-76x76.png"> + <link rel="apple-touch-icon" sizes="114x114" href="images/apple-icon-114x114.png"> + <link rel="apple-touch-icon" sizes="120x120" href="images/apple-icon-120x120.png"> + <link rel="apple-touch-icon" sizes="144x144" href="images/apple-icon-144x144.png"> + <link rel="apple-touch-icon" sizes="152x152" href="images/apple-icon-152x152.png"> + <link rel="apple-touch-icon" sizes="180x180" href="images/apple-icon-180x180.png"> + <link rel="icon" type="image/png" sizes="192x192" href="images/android-icon-192x192.png"> + <link rel="icon" type="image/png" sizes="32x32" href="images/favicon-32x32.png"> + <link rel="icon" type="image/png" sizes="96x96" href="images/favicon-96x96.png"> + <link rel="icon" type="image/png" sizes="16x16" href="images/favicon-16x16.png"> + <link rel="manifest" href="manifest.json"> + <meta name="msapplication-TileColor" content="#ffffff"> + <meta name="msapplication-TileImage" content="images/ms-icon-144x144.png"> + <meta name="theme-color" content="#ffffff"> --> <meta property="og:locale" content="en_US" /> <meta property="og:url" content="https://my-netdata.io" /> @@ -48,4494 +51,7 @@ <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> - - /* force the vertical window scrollbar */ - html { - overflow-y: scroll; - } - - /* prevent body from hiding under the navbar */ - body { - padding-top: 50px; - } - - .loadOverlay { - position: absolute; - top: 0px; - left: 0px; - width: 100%; - height:100%; - z-index: 2000; - font-size: 10vh; - font-family: sans-serif; - padding: 40vh 0 40vh 0; - font-weight: bold; - text-align: center; - } - - .navbar-highlight { - display: none; - position: fixed; - margin-top: 5px; - height: 26px; - width: 100%; - text-align: center; - overflow: hidden; - z-index: 30; - pointer-events: none !important; - } - - .navbar-highlight-content { - position: relative; - display: inline-block; - margin: 0 auto; - height: 26px; - min-width: 500px; - background-color:rgba(0, 0, 0, 0.7); - padding-top: 2px; - padding-bottom: 2px; - padding-left: 15px; - padding-right: 15px; - border-radius:10px; - color: lightgrey; - pointer-events: auto !important; - } - - .navbar-highlight-bar { - cursor: pointer; - } - .navbar-highlight-button-right { - cursor: pointer; - padding-left: 10px; - } - - .modal-wide .modal-dialog { - width: 80%; - } - - /* fix # anchors scrolling under the navbar - https://github.com/twbs/bootstrap/issues/1768#issuecomment-46519033 - */ - h1 { - position: relative; - z-index: -1; - } - h2 { - position: relative; - z-index: -2; - } - h1:before, h2:before { - display: block; - content: " "; - margin-top: -70px; - height: 70px; - visibility: hidden; - } - - .p { - display: block; - margin-top: 15px; - } - - .option-row, - .option-control { - vertical-align: top; - padding: 10px; - padding-top: 30px; - padding-left: 30px; - } - - .option-info { - padding: 10px; - } - - .dashboard-submenu-info { - display: block; - margin-top: 10px; - } - - .dashboard-context-info { - display: block; - margin-top: 10px; - } - - #masthead h1 { - /*font-size: 30px;*/ - line-height: 1; - padding-top: 30px; - } - - #masthead .well { - margin-top:4%; - } - - /* fix the navbar shifting when a modal is open */ - /* https://github.com/twbs/bootstrap/issues/14040#issuecomment-159891033 */ - body.modal-open{ - width: 100% !important; - padding-right: 0 !important; -/* overflow-y: scroll !important; */ -/* position: fixed !important;*/ - overflow: visible; - } - - /* make accordion use the whole header bar for expand/collapse */ - .panel-title a { - display: block; - padding: 10px 15px; - margin: -10px -15px; - } - - /* - * Side navigation - * - * Scrollspy and affixed enhanced navigation to highlight sections and secondary - * sections of docs content. - */ - - .affix { - position: static; - top: 70px !important; - /*width: 220px;*/ - } - - .affix-top { - /*width: 220px;*/ - } - - .dashboard-sidebar { - max-height: calc(100% - 70px) !important; - overflow-y: auto; - /*width: 220px !important;*/ - } - - /* By default it's not affixed in mobile views, so undo that */ - .dashboard-sidebar.affix { - position: static; - } - - @media (min-width: 768px) { - .dashboard-sidebar { - padding-left: 20px; - } - } - - /* First level of nav */ - .dashboard-sidenav { - margin-top: 20px; - margin-bottom: 20px; - } - - /* All levels of nav */ - .dashboard-sidebar .nav > li > a { - display: block; - padding: 4px 20px; - font-size: 13px; - font-weight: 500; - color: #767676; - } - .dashboard-sidebar .nav > li > a > .svg-inline--fa { - width: 20px; - text-align: center; - } - .dashboard-sidebar .nav > li > a:hover, - .dashboard-sidebar .nav > li > a:focus { - padding-left: 19px; - color: #563d7c; - text-decoration: none; - background-color: transparent; - border-left: 1px solid #563d7c; - } - .dashboard-sidebar .nav > .active > a, - .dashboard-sidebar .nav > .active:hover > a, - .dashboard-sidebar .nav > .active:focus > a { - padding-left: 18px; - font-weight: bold; - color: #563d7c; - background-color: transparent; - border-left: 2px solid #563d7c; - } - - /* Nav: second level (shown on .active) */ - .dashboard-sidebar .nav .nav { - display: none; /* Hide by default, but at >768px, show it */ - padding-bottom: 10px; - } - .dashboard-sidebar .nav .nav > li > a { - padding-top: 1px; - padding-bottom: 1px; - padding-left: 30px; - font-size: 12px; - font-weight: normal; - } - .dashboard-sidebar .nav .nav > li > a:hover, - .dashboard-sidebar .nav .nav > li > a:focus { - padding-left: 29px; - } - .dashboard-sidebar .nav .nav > .active > a, - .dashboard-sidebar .nav .nav > .active:hover > a, - .dashboard-sidebar .nav .nav > .active:focus > a { - padding-left: 28px; - font-weight: 500; - } - - .dropdown-menu { - min-width: 200px; - } - .dropdown-menu.columns-2 { - margin: 0; - padding: 0; - width: 400px; - } - .dropdown-menu li a { - padding: 5px 15px; - font-weight: 300; - } - .dropdown-menu.multi-column { - overflow-x: hidden; - } - .multi-column-dropdown { - list-style: none; - padding: 0; - } - .multi-column-dropdown li a { - display: block; - clear: both; - line-height: 1.428571429; - white-space: normal; - } - .multi-column-dropdown li a:hover { - text-decoration: none; - color: #f5f5f5; - background-color: #262626; - } - .scrollable-menu { - height: auto; - max-height: 80vh; - overflow-x: hidden; - } - .scrollable-menu-50 { - height: auto; - max-height: 50vh; - overflow-x: hidden; - } - - /* Back to top (hidden on mobile) */ - .back-to-top, - .dashboard-theme-toggle { - display: none; - padding: 4px 10px; - margin-top: 10px; - margin-left: 10px; - font-size: 12px; - font-weight: 500; - color: #999; - } - .back-to-top:hover, - .dashboard-theme-toggle:hover { - color: #563d7c; - text-decoration: none; - } - .dashboard-theme-toggle { - margin-top: 0; - } - - .container { - width: calc(100% - 20px) !important; - } - - .charts-body { - display: inline-block; - width: 100%; - } - - .sidebar-body { - position: absolute; - display: none; - } - - .dashboard-section-container { - display: block; - width: 100%; - page-break-before: auto; - page-break-after: auto; - page-break-inside: auto; - } - - .dashboard-print-row { - display: block; - width: 100%; - page-break-before: auto; - page-break-after: auto; - page-break-inside: avoid; - } - - .netdata-chartblock-container { - display: inline-block; - } - - /* https://github.com/seiyria/bootstrap-slider/issues/746 */ - .tooltip { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - } - - @media print { - body { - overflow: visible !important; - -webkit-print-color-adjust: exact; - page-break-inside: auto; - page-break-before: auto; - page-break-after: auto; - } - - .dashboard-section { - page-break-inside: auto; - page-break-before: auto; - page-break-after: auto; - } - - .dashboard-subsection { - page-break-before: avoid; - page-break-after: auto; - page-break-inside: auto; - } - - .charts-body { - padding-left: 0%; - padding-right: 0%; - display: block; - page-break-inside: auto; - page-break-before: auto; - page-break-after: auto; - } - - .back-to-top, - .dashboard-theme-toggle { - display: block; - } - } - - @media (min-width: 768px) { - .charts-body { - padding-left: 0%; - padding-right: 0%; - } - - .back-to-top, - .dashboard-theme-toggle { - display: block; - } - } - - /* Show and affix the side nav when space allows it */ - @media (min-width: 992px) { - .container { - padding-left: 0% !important; - } - - .charts-body { - width: calc(100% - 213px) !important; - padding-left: 1% !important; - padding-right: 0% !important; - } - - .sidebar-body { - display: inline-block !important; - width: 213px !important; - } - - .dashboard-sidebar .nav > .active > ul { - display: block; - } - - /* Widen the fixed sidebar */ - .dashboard-sidebar.affix, - .dashboard-sidebar.affix-top, - .dashboard-sidebar.affix-bottom { - width: 213px !important; - } - .dashboard-sidebar.affix { - position: fixed; /* Undo the static from mobile first approach */ - top: 20px; - } - .dashboard-sidebar.affix-bottom { - position: absolute; /* Undo the static from mobile first approach */ - } - .dashboard-sidebar.affix-bottom .dashboard-sidenav, - .dashboard-sidebar.affix .dashboard-sidenav { - margin-top: 0; - margin-bottom: 0; - } - } - - @media (min-width: 1200px) { - .container { - padding-left: 2% !important; - } - - .charts-body { - width: calc(100% - 233px) !important; - padding-left: 1% !important; - padding-right: 1% !important; - } - - .sidebar-body { - display: inline-block !important; - width: 233px !important; - } - - /* Widen the fixed sidebar again */ - .dashboard-sidebar.affix, - .dashboard-sidebar.affix-top, - .dashboard-sidebar.affix-bottom { - width: 233px !important; - } - } - - @media (min-width: 1360px) { - .container { - padding-left: 3% !important; - } - - .charts-body { - width: calc(100% - 263px) !important; - padding-left: 1% !important; - padding-right: 2% !important; - } - - .sidebar-body { - display: inline-block !important; - width: 263px !important; - } - - /* Widen the fixed sidebar again */ - .dashboard-sidebar.affix, - .dashboard-sidebar.affix-top, - .dashboard-sidebar.affix-bottom { - width: 263px !important; - } - } - - .action-button { - position: relative; - display: inline-block; - color: gray; - cursor: pointer; - margin: 0 auto; - width: 30px; - height: 30px; - font-size: 25px; - } - - .ripple { - position: relative; - /*overflow: hidden;*/ - transform: translate3d(0, 0, 0) - } - - .ripple:after { - content: ""; - display: block; - position: absolute; - width: 100%; - height: 100%; - top: 0; - left: 0; - pointer-events: none; - background-image: radial-gradient(circle, #000 10%, transparent 10.01%); - background-repeat: no-repeat; - background-position: 50%; - transform: scale(18, 18); /* the size of the ripple */ - opacity: 0; - transition: transform .5s, opacity 1s - } - - .ripple:active:after { - transform: scale(0, 0); - opacity: .2; - transition: 0s - } - </style> - - <!-- check which theme to use --> - <script type="text/javascript"> - // netdata snapshot data - var netdataSnapshotData = null; - - // enable alarms checking and notifications - var netdataShowAlarms = true; - - // enable registry updates - var netdataRegistry = true; - - // forward definition only - not used here - var netdataServer = undefined; - var netdataServerStatic = undefined; - var netdataCheckXSS = undefined; - - // control the welcome modal and analytics - var this_is_demo = null; - - function escapeUserInputHTML(s) { - return s.toString() - .replace(/&/g, '&') - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/"/g, '"') - .replace(/#/g, '#') - .replace(/'/g, ''') - .replace(/\(/g,'(') - .replace(/\)/g,')') - .replace(/\//g,'/'); - } - - function verifyURL(s) { - if(typeof(s) === 'string' && (s.startsWith('http://') || s.startsWith('https://'))) - return s - .replace(/'/g, '%22') - .replace(/"/g, '%27') - .replace(/\)/g, '%28') - .replace(/\(/g, '%29'); - - console.log('invalid URL detected:'); - console.log(s); - return 'javascript:alert("invalid url");'; - } - - // -------------------------------------------------------------------- - // urlOptions - - var urlOptions = { - hash: '#', - theme: null, - help: null, - mode: 'live', // 'live', 'print' - update_always: false, - pan_and_zoom: false, - server: null, - after: 0, - before: 0, - highlight: false, - highlight_after: 0, - highlight_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(forReload) { - var hash = urlOptions.hash; - - if(urlOptions.pan_and_zoom === true) { - hash += ';after=' + urlOptions.after.toString() + - ';before=' + urlOptions.before.toString(); - } - - if(urlOptions.highlight === true) { - hash += ';highlight_after=' + urlOptions.highlight_after.toString() + - ';highlight_before=' + urlOptions.highlight_before.toString(); - } - - if(urlOptions.theme !== null) - hash += ';theme=' + urlOptions.theme.toString(); - - if(urlOptions.help !== null) - hash += ';help=' + urlOptions.help.toString(); - - if(urlOptions.update_always === true) - hash += ';update_always=true'; - - if(forReload === true && urlOptions.server !== null) - hash += ';server=' + urlOptions.server.toString(); - - if(urlOptions.mode !== 'live') - hash += ';mode=' + urlOptions.mode; - - return hash; - }, - - 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]; - } - } - - var booleans = [ 'nowelcome', 'show_alarms', '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; - } - - var numeric = [ 'after', 'before', 'highlight_after', 'highlight_before' ]; - len = numeric.length; - while(len--) { - if(typeof urlOptions[numeric[len]] === 'string') { - try { - urlOptions[numeric[len]] = parseInt(urlOptions[numeric[len]]); - } - catch(e) { - console.log('failed to parse URL hash parameter ' + numeric[len]); - urlOptions[numeric[len]] = 0; - } - } - } - - if(urlOptions.server !== null && urlOptions.server !== '') { - netdataServerStatic = document.location.origin.toString() + document.location.pathname.toString(); - netdataServer = urlOptions.server; - netdataCheckXSS = true; - } - else - urlOptions.server = null; - - if(urlOptions.before > 0 && urlOptions.after > 0) { - urlOptions.pan_and_zoom = true; - urlOptions.nowelcome = true; - } - else - urlOptions.pan_and_zoom = false; - - if(urlOptions.highlight_before > 0 && urlOptions.highlight_after > 0) { - urlOptions.highlight = true; - } - else - urlOptions.highlight = false; - - switch(urlOptions.mode) { - case 'print': - urlOptions.theme = 'white'; - urlOptions.welcome = false; - urlOptions.help = false; - urlOptions.show_alarms = false; - - if(urlOptions.pan_and_zoom === false) { - urlOptions.pan_and_zoom = true; - urlOptions.before = Date.now(); - urlOptions.after = urlOptions.before - 600000; - } - - netdataShowAlarms = false; - netdataRegistry = false; - this_is_demo = false; - break; - - case 'live': - default: - urlOptions.mode = 'live'; - break; - } - - // console.log(urlOptions); - }, - - hashUpdate: function() { - history.replaceState(null, '', urlOptions.genHash(true)); - }, - - netdataPanAndZoomCallback: function(status, after, before) { - //console.log(1); - //console.log(new Error().stack); - - if(netdataSnapshotData === null) { - urlOptions.pan_and_zoom = status; - urlOptions.after = after; - urlOptions.before = before; - urlOptions.hashUpdate(); - } - }, - - netdataHighlightCallback: function(status, after, before) { - //console.log(2); - //console.log(new Error().stack); - - if(status === true && (after === null || before === null || after <= 0 || before <= 0 || after >= before)) { - status = false; - after = 0; - before = 0; - } - - if(netdataSnapshotData === null) - urlOptions.highlight = status; - else - urlOptions.highlight = false; - - urlOptions.highlight_after = Math.round(after); - urlOptions.highlight_before = Math.round(before); - urlOptions.hashUpdate(); - - var show_eye = NETDATA.globalChartUnderlay.hasViewport(); - - if(status === true && after > 0 && before > 0 && after < before) { - var d1 = NETDATA.dateTime.localeDateString(after); - var d2 = NETDATA.dateTime.localeDateString(before); - if(d1 === d2) d2 = ''; - document.getElementById('navbar-highlight-content').innerHTML = - ((show_eye === true)?'<span class="navbar-highlight-bar highlight-tooltip" onclick="urlOptions.showHighlight();" title="restore the highlighted view" data-toggle="tooltip" data-placement="bottom">':'<span>').toString() - + 'highlighted time-frame' - + ' <b>' + d1 + ' <code>' + NETDATA.dateTime.localeTimeString(after) + '</code></b> to ' - + ' <b>' + d2 + ' <code>' + NETDATA.dateTime.localeTimeString(before) + '</code></b>, ' - + 'duration <b>' + NETDATA.seconds4human(Math.round((before - after) / 1000)) + '</b>' - + '</span>' - + '<span class="navbar-highlight-button-right highlight-tooltip" onclick="urlOptions.clearHighlight();" title="clear the highlighted time-frame" data-toggle="tooltip" data-placement="bottom"><i class="fas fa-times"></i></span>'; - - $('.navbar-highlight').show(); - - $('.highlight-tooltip').tooltip({ - html: true, - delay: {show: 500, hide: 0}, - container: 'body' - }); - } - else - $('.navbar-highlight').hide(); - }, - - clearHighlight: function() { - NETDATA.globalChartUnderlay.clear(); - - if(NETDATA.globalPanAndZoom.isActive() === true) - NETDATA.globalPanAndZoom.clearMaster(); - }, - - showHighlight: function() { - NETDATA.globalChartUnderlay.focus(); - } - }; - - urlOptions.parseHash(); - - // -------------------------------------------------------------------- - // check options that should be processed before loading netdata.js - - var localStorageTested = -1; - function localStorageTest() { - if(localStorageTested !== -1) - return localStorageTested; - - if(typeof Storage !== "undefined" && typeof localStorage === 'object') { - var test = 'test'; - try { - localStorage.setItem(test, test); - localStorage.removeItem(test); - localStorageTested = true; - } - catch (e) { - console.log(e); - localStorageTested = false; - } - } - else - localStorageTested = false; - - return localStorageTested; - } - - function loadLocalStorage(name) { - var ret = null; - - try { - if(localStorageTest() === true) - ret = localStorage.getItem(name); - else - console.log('localStorage is not available'); - } - catch(error) { - console.log(error); - return null; - } - - if(typeof ret === 'undefined' || ret === null) - return null; - - // console.log('loaded: ' + name.toString() + ' = ' + ret.toString()); - - return ret; - } - - function saveLocalStorage(name, value) { - // console.log('saving: ' + name.toString() + ' = ' + value.toString()); - try { - if(localStorageTest() === true) { - localStorage.setItem(name, value.toString()); - return true; - } - } - catch(error) { - console.log(error); - } - - return false; - } - - function getTheme(def) { - if(urlOptions.mode === 'print') - return 'white'; - - var ret = loadLocalStorage('netdataTheme'); - if(typeof ret === 'undefined' || ret === null || ret === 'undefined') - return def; - else - return ret; - } - - function setTheme(theme) { - if(urlOptions.mode === 'print') return false; - - if(theme === netdataTheme) return false; - return saveLocalStorage('netdataTheme', theme); - } - - var netdataTheme = getTheme('slate'); - var netdataShowHelp = true; - - if(urlOptions.theme !== null) { - setTheme(urlOptions.theme); - netdataTheme = urlOptions.theme; - } - else - urlOptions.theme = netdataTheme; - - if(urlOptions.help !== null) { - saveLocalStorage('options.show_help', urlOptions.help); - netdataShowHelp = urlOptions.help; - } - else { - urlOptions.help = loadLocalStorage('options.show_help'); - } - - // -------------------------------------------------------------------- - // natural sorting - // http://www.davekoelle.com/files/alphanum.js - LGPL - - function naturalSortChunkify(t) { - var tz = []; - var x = 0, y = -1, n = 0, i, j; - - while (i = (j = t.charAt(x++)).charCodeAt(0)) { - var m = (i >= 48 && i <= 57); - if (m !== n) { - tz[++y] = ""; - n = m; - } - tz[y] += j; - } - - return tz; - } - - function naturalSortCompare(a, b) { - var aa = naturalSortChunkify(a.toLowerCase()); - var bb = naturalSortChunkify(b.toLowerCase()); - - for (var x = 0; aa[x] && bb[x]; x++) { - if (aa[x] !== bb[x]) { - var c = Number(aa[x]), d = Number(bb[x]); - if (c.toString() === aa[x] && d.toString() === bb[x]) - return c - d; - else - return (aa[x] > bb[x]) ? 1 : -1; - } - } - - return aa.length - bb.length; - } - - // -------------------------------------------------------------------- - // saving files to client - - function saveTextToClient(data, filename) { - var blob = new Blob( [ data ], { - type: 'application/octet-stream' - }); - - var url = URL.createObjectURL( blob ); - var link = document.createElement( 'a' ); - link.setAttribute( 'href', url ); - link.setAttribute( 'download', filename ); - - var el = document.getElementById('hiddenDownloadLinks'); - el.innerHTML = ''; - el.appendChild(link); - - setTimeout(function(){ - el.removeChild(link); - URL.revokeObjectURL(url); - }, 60); - - link.click(); - } - - function saveObjectToClient(data, filename) { - saveTextToClient(JSON.stringify(data), filename); - } - - // -------------------------------------------------------------------- - // registry call back to render my-netdata menu - - var netdataRegistryCallback = function(machines_array) { - var el = ''; - var a1 = ''; - var found = 0, hosted = 0; - var len, i, url, hostname, icon; - - if(options.hosts.length > 1) { - // there are mirrored hosts here - - el += '<li><a href="#" onClick="return false;" style="color: #666;" target="_blank">databases available on this host</a></li>'; - a1 += '<li><a href="#" onClick="return false;"><i class="fas fa-info-circle" style="color: #666;"></i></a></li>'; - - var base = document.location.origin.toString() + document.location.pathname.toString(); - if(base.endsWith("/host/" + options.hostname + "/")) - base = base.substring(0, base.length - ("/host/" + options.hostname + "/").toString().length); - - if(base.endsWith("/")) - base = base.substring(0, base.length - 1); - - var master = options.hosts[0].hostname; - var sorted = options.hosts.sort(function(a, b) { - if(a.hostname === master) return -1; - return naturalSortCompare(a.hostname, b.hostname); - }); - - i = 0; - len = sorted.length; - while(len--) { - hostname = sorted[i].hostname; - if(hostname === master) { - url = base + "/"; - icon = "home"; - } - else { - url = base + "/host/" + hostname + "/"; - icon = "window-restore"; - } - - el += '<li id="registry_server_hosted_' + len.toString() + '"><a class="registry_link" href="' + url + '#" onClick="return gotoHostedModalHandler(\'' + url + '\');">' + hostname + '</a></li>'; - a1 += '<li id="registry_action_hosted_' + len.toString() + '"><a class="registry_link" href="' + url + '#" onClick="return gotoHostedModalHandler(\'' + url + '\');"><i class="fas fa-' + icon + '" style="color: #999;"></i></a></li>'; - hosted++; - i++; - } - - el += '<li role="separator" class="divider"></li>'; - a1 += '<li role="separator" class="divider"></li>'; - } - - if(machines_array === null) { - var ret = loadLocalStorage("registryCallback"); - if(typeof ret !== 'undefined' && ret !== null) { - machines_array = JSON.parse(ret); - console.log("failed to contact the registry - loaded registry data from browser local storage"); - } - } - - if(machines_array) { - saveLocalStorage("registryCallback", JSON.stringify(machines_array)); - - var machines = machines_array.sort(function (a, b) { - return naturalSortCompare(a.name, b.name); - }); - - i = 0; - len = machines.length; - while(len--) { - var u = machines[i++]; - 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="fas fa-trash" style="color: #999;"></i></a></li>'; - } - } - - if(!found) { - if(machines) - el += '<li><a href="https://github.com/netdata/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/netdata/netdata/wiki/mynetdata-menu-item" style="color: #666;" target="_blank">failed to contact the registry...</a></li>'; - - a1 += '<li><a href="#" onClick="return false;"> </a></li>'; - - el += '<li role="separator" class="divider"></li>' + - '<li><a href="//london.netdata.rocks/default.html">UK - London (DigitalOcean.com)</a></li>' + - '<li><a href="//newyork.netdata.rocks/default.html">US - New York (DigitalOcean.com)</a></li>' + - '<li><a href="//sanfrancisco.netdata.rocks/default.html">US - San Francisco (DigitalOcean.com)</a></li>' + - '<li><a href="//atlanta.netdata.rocks/default.html">US - Atlanta (CDN77.com)</a></li>' + - '<li><a href="//frankfurt.netdata.rocks/default.html">Germany - Frankfurt (DigitalOcean.com)</a></li>' + - '<li><a href="//toronto.netdata.rocks/default.html">Canada - Toronto (DigitalOcean.com)</a></li>' + - '<li><a href="//singapore.netdata.rocks/default.html">Japan - Singapore (DigitalOcean.com)</a></li>' + - '<li><a href="//bangalore.netdata.rocks/default.html">India - Bangalore (DigitalOcean.com)</a></li>'; - a1 += '<li role="separator" class="divider"></li>' + - '<li><a href="#"> </a></li>' + - '<li><a href="#"> </a></li>'+ - '<li><a href="#"> </a></li>'+ - '<li><a href="#"> </a></li>'+ - '<li><a href="#"> </a></li>'+ - '<li><a href="#"> </a></li>'+ - '<li><a href="#"> </a></li>'+ - '<li><a href="#"> </a></li>'; - } - - el += '<li role="separator" class="divider"></li>'; - a1 += '<li role="separator" class="divider"></li>'; - - el += '<li><a href="https://github.com/netdata/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="fas fa-cog" 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(); - }; - - 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('.netdata.ai') || - document.location.hostname.endsWith('.netdata.live') || - document.location.hostname.endsWith('.firehol.org') || - document.location.hostname.endsWith('.netdata.online') || - document.location.hostname.endsWith('.netdata.cloud')) - this_is_demo = true; - } - } - catch(error) {} - return this_is_demo; - } - - function netdataURL(url, forReload) { - if(typeof url === 'undefined') - // url = document.location.toString(); - url = ''; - - if(url.indexOf('#') !== -1) - url = url.substring(0, url.indexOf('#')); - - var hash = urlOptions.genHash(forReload); - - // console.log('netdataURL: ' + url + hash); - - return url + hash; - } - - function netdataReload(url) { - document.location = verifyURL(netdataURL(url, true)); - - // since we play with hash - // this is needed to reload the page - location.reload(); - } - - function gotoHostedModalHandler(url) { - document.location = verifyURL(url + urlOptions.genHash()); - return false; - } - - var gotoServerValidateRemaining = 0; - var gotoServerMiddleClick = false; - var gotoServerStop = false; - function gotoServerValidateUrl(id, guid, url) { - var penalty = 0; - var error = 'failed'; - - if(document.location.toString().startsWith('http://') && url.toString().startsWith('https://')) - // we penalize https only if the current url is http - // to allow the user walk through all its servers. - penalty = 500; - - else if(document.location.toString().startsWith('https://') && url.toString().startsWith('http://')) - error = 'can\'t check'; - - var finalURL = netdataURL(url); - - setTimeout(function() { - document.getElementById('gotoServerList').innerHTML += '<tr><td style="padding-left: 20px;"><a href="' + verifyURL(finalURL) + '" target="_blank">' + escapeUserInputHTML(url) + '</a></td><td style="padding-left: 30px;"><code id="' + guid + '-' + id + '-status">checking...</code></td></tr>'; - - NETDATA.registry.hello(url, function(data) { - if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid === guid) { - // console.log('OK ' + id + ' URL: ' + url); - document.getElementById(guid + '-' + id + '-status').innerHTML = "OK"; - - if(!gotoServerStop) { - gotoServerStop = true; - - if(gotoServerMiddleClick) { - window.open(verifyURL(finalURL), '_blank'); - gotoServerMiddleClick = false; - document.getElementById('gotoServerResponse').innerHTML = '<b>Opening new window to ' + NETDATA.registry.machines[guid].name + '<br/><a href="' + verifyURL(finalURL) + '">' + escapeUserInputHTML(url) + '</a></b><br/>(check your pop-up blocker if it fails)'; - } - else { - document.getElementById('gotoServerResponse').innerHTML += 'found it! It is at:<br/><small>' + escapeUserInputHTML(url) + '</small>'; - document.location = verifyURL(finalURL); - } - } - } - else { - if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid !== guid) - error = 'wrong machine'; - - document.getElementById(guid + '-' + id + '-status').innerHTML = error; - gotoServerValidateRemaining--; - if(gotoServerValidateRemaining <= 0) { - gotoServerMiddleClick = false; - document.getElementById('gotoServerResponse').innerHTML = '<b>Sorry! I cannot find any operational URL for this server</b>'; - } - } - }); - }, (id * 50) + penalty); - } - - function gotoServerModalHandler(guid) { - // console.log('goto server: ' + guid); - - gotoServerStop = false; - var checked = {}; - var len = NETDATA.registry.machines[guid].alternate_urls.length; - var count = 0; - - document.getElementById('gotoServerResponse').innerHTML = ''; - document.getElementById('gotoServerList').innerHTML = ''; - document.getElementById('gotoServerName').innerHTML = NETDATA.registry.machines[guid].name; - $('#gotoServerModal').modal('show'); - - gotoServerValidateRemaining = len; - while(len--) { - var url = NETDATA.registry.machines[guid].alternate_urls[len]; - checked[url] = true; - gotoServerValidateUrl(count++, guid, url); - } - - setTimeout(function() { - if(gotoServerStop === false) { - document.getElementById('gotoServerResponse').innerHTML = '<b>Added all the known URLs for this machine.</b>'; - NETDATA.registry.search(guid, function(data) { - // console.log(data); - len = data.urls.length; - while(len--) { - var url = data.urls[len][1]; - // console.log(url); - if(typeof checked[url] === 'undefined') { - gotoServerValidateRemaining++; - checked[url] = true; - gotoServerValidateUrl(count++, guid, url); - } - } - }); - } - }, 2000); - return false; - } - - function gotoServerInit() { - $(".registry_link").on('click', function(e) { - if(e.which === 2) { - e.preventDefault(); - gotoServerMiddleClick = true; - } - else { - gotoServerMiddleClick = false; - } - - return true; - }); - } - - function switchRegistryModalHandler() { - document.getElementById('switchRegistryPersonGUID').value = NETDATA.registry.person_guid; - document.getElementById('switchRegistryURL').innerHTML = NETDATA.registry.server; - document.getElementById('switchRegistryResponse').innerHTML = ''; - $('#switchRegistryModal').modal('show'); - } - - function notifyForSwitchRegistry() { - var n = document.getElementById('switchRegistryPersonGUID').value; - - if(n !== '' && n.length === 36) { - NETDATA.registry.switch(n, function(result) { - if(result !== null) { - $('#switchRegistryModal').modal('hide'); - NETDATA.registry.init(); - } - else { - document.getElementById('switchRegistryResponse').innerHTML = "<b>Sorry! The registry rejected your request.</b>"; - } - }); - } - else - document.getElementById('switchRegistryResponse').innerHTML = "<b>The ID you have entered is not a GUID.</b>"; - } - - var deleteRegistryUrl = null; - function deleteRegistryModalHandler(guid, name, url) { - void(guid); - - deleteRegistryUrl = url; - document.getElementById('deleteRegistryServerName').innerHTML = name; - document.getElementById('deleteRegistryServerName2').innerHTML = name; - document.getElementById('deleteRegistryServerURL').innerHTML = url; - document.getElementById('deleteRegistryResponse').innerHTML = ''; - $('#deleteRegistryModal').modal('show'); - } - - function notifyForDeleteRegistry() { - if(deleteRegistryUrl) { - NETDATA.registry.delete(deleteRegistryUrl, function(result) { - if(result !== null) { - deleteRegistryUrl = null; - $('#deleteRegistryModal').modal('hide'); - NETDATA.registry.init(); - } - else { - document.getElementById('deleteRegistryResponse').innerHTML = "<b>Sorry! this command was rejected by the registry server.</b>"; - } - }); - } - } - - var options = { - menus: {}, - submenu_names: {}, - data: null, - hostname: 'netdata_server', // will be overwritten by the netdata server - version: 'unknown', - hosts: [], - - duration: 0, // the default duration of the charts - update_every: 1, - - chartsPerRow: 0, - // chartsMinWidth: 1450, - chartsHeight: 180, - }; - - function chartsPerRow(total) { - void(total); - - if(options.chartsPerRow === 0) { - return 1; - //var width = Math.floor(total / options.chartsMinWidth); - //if(width === 0) width = 1; - //return width; - } - else return options.chartsPerRow; - } - - function prioritySort(a, b) { - if(a.priority < b.priority) return -1; - if(a.priority > b.priority) return 1; - return naturalSortCompare(a.name, b.name); - } - - function sortObjectByPriority(object) { - var idx = {}; - var sorted = []; - - for(var i in object) { - if(!object.hasOwnProperty(i)) continue; - - if(typeof idx[i] === 'undefined') { - idx[i] = object[i]; - sorted.push(i); - } - } - - sorted.sort(function(a, b) { - if(idx[a].priority < idx[b].priority) return -1; - if(idx[a].priority > idx[b].priority) return 1; - return naturalSortCompare(a, b); - }); - - return sorted; - } - - - // ---------------------------------------------------------------------------- - // scroll to a section, without changing the browser history - - function scrollToId(hash) { - if(hash && hash !== '' && document.getElementById(hash) !== null) { - var offset = $('#' + hash).offset(); - if(typeof offset !== 'undefined') { - //console.log('scrolling to ' + hash + ' at ' + offset.top.toString()); - $('html, body').animate({scrollTop: offset.top - 30}, 0); - } - } - - // we must return false to prevent the default action - return false; - } - - // ---------------------------------------------------------------------------- - - // user editable information - var customDashboard = { - menu: {}, - submenu: {}, - context: {} - }; - - // netdata standard information - var netdataDashboard = { - sparklines_registry: {}, - os: 'unknown', - - menu: {}, - submenu: {}, - context: {}, - - // generate a sparkline - // used in the documentation - sparkline: function (prefix, chart, dimension, units, suffix) { - if(options.data === null || typeof options.data.charts === 'undefined') - return ''; - - if(typeof options.data.charts[chart] === 'undefined') - return ''; - - if(typeof options.data.charts[chart].dimensions === 'undefined') - return ''; - - if(typeof options.data.charts[chart].dimensions[dimension] === 'undefined') - return ''; - - var key = chart + '.' + dimension; - - if(typeof units === 'undefined') - units = ''; - - if(typeof this.sparklines_registry[key] === 'undefined') - this.sparklines_registry[key] = { count: 1 }; - else - this.sparklines_registry[key].count++; - - key = key + '.' + this.sparklines_registry[key].count; - - return prefix + '<div class="netdata-container" data-netdata="' + chart + '" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dimensions="' + dimension + '" data-show-value-of-' + dimension + '-at="' + key + '"></div> (<span id="' + key + '" style="display: inline-block; min-width: 50px; text-align: right;">X</span>' + units + ')' + suffix; - }, - - gaugeChart: function(title, width, dimensions, colors) { - if(typeof colors === 'undefined') - colors = ''; - - if(typeof dimensions === 'undefined') - dimensions = ''; - - return '<div class="netdata-container" 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') { - var x = obj[key][attr]; - - if(typeof(x) === 'undefined') - return def; - - if(typeof(x) === 'function') { - return x(netdataDashboard.os); - } - - return x; - } - - return def; - }, - - menuTitle: function(chart) { - if(typeof chart.menu_pattern !== 'undefined') { - return (this.anyAttribute(this.menu, 'title', chart.menu_pattern, chart.menu_pattern).toString() - + ' ' + chart.type.slice(-(chart.type.length - chart.menu_pattern.length - 1)).toString()).replace(/_/g, ' '); - } - - return (this.anyAttribute(this.menu, 'title', chart.menu, chart.menu)).toString().replace(/_/g, ' '); - }, - - menuIcon: function(chart) { - if(typeof chart.menu_pattern !== 'undefined') - return this.anyAttribute(this.menu, 'icon', chart.menu_pattern, '<i class="fas fa-puzzle-piece"></i>').toString(); - - return this.anyAttribute(this.menu, 'icon', chart.menu, '<i class="fas fa-puzzle-piece"></i>'); - }, - - menuInfo: function(chart) { - if(typeof chart.menu_pattern !== 'undefined') - return this.anyAttribute(this.menu, 'info', chart.menu_pattern, null); - - return this.anyAttribute(this.menu, 'info', chart.menu, null); - }, - - menuHeight: function(chart) { - if(typeof chart.menu_pattern !== 'undefined') - return this.anyAttribute(this.menu, 'height', chart.menu_pattern, 1.0); - - return this.anyAttribute(this.menu, 'height', chart.menu, 1.0); - }, - - submenuTitle: function(menu, submenu) { - var key = menu + '.' + submenu; - // console.log(key); - var title = this.anyAttribute(this.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 this.anyAttribute(this.submenu, 'info', key, null); - }, - - submenuHeight: function(menu, submenu, relative) { - var key = menu + '.' + submenu; - return this.anyAttribute(this.submenu, 'height', key, 1.0) * relative; - }, - - contextInfo: function(id) { - var x = this.anyAttribute(this.context, 'info', id, null); - - if(x !== null) - return '<div class="shorten dashboard-context-info netdata-chart-alignment" role="document">' + x + '</div>'; - else - return ''; - }, - - contextValueRange: function(id) { - if(typeof this.context[id] !== 'undefined' && typeof this.context[id].valueRange !== 'undefined') - return this.context[id].valueRange; - else - return '[null, null]'; - }, - - contextHeight: function(id, def) { - if(typeof this.context[id] !== 'undefined' && typeof this.context[id].height !== 'undefined') - return def * this.context[id].height; - else - return def; - }, - - contextDecimalDigits: function(id, def) { - if(typeof this.context[id] !== 'undefined' && typeof this.context[id].decimalDigits !== 'undefined') - return this.context[id].decimalDigits; - else - return def; - } - }; - - // ---------------------------------------------------------------------------- - - // enrich the data structure returned by netdata - // to reflect our menu system and content - // TODO: this is a shame - we should fix charts naming (issue #807) - function enrichChartData(chart) { - var parts = chart.type.split('_'); - var tmp = parts[0]; - - switch(tmp) { - case 'ap': - case 'net': - case 'disk': - case 'statsd': - chart.menu = tmp; - break; - - case 'apache': - chart.menu = chart.type; - if(parts.length > 2 && parts[1] === 'cache') - chart.menu_pattern = tmp + '_' + parts[1]; - else if(parts.length > 1) - chart.menu_pattern = tmp; - break; - - case 'bind': - chart.menu = chart.type; - if(parts.length > 2 && parts[1] === 'rndc') - chart.menu_pattern = tmp + '_' + parts[1]; - else if(parts.length > 1) - chart.menu_pattern = 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 'go': - chart.menu = chart.type; - if(parts.length > 2 && parts[1] === 'expvar') - chart.menu_pattern = tmp + '_' + parts[1]; - else if(parts.length > 1) - chart.menu_pattern = tmp; - break; - - case 'isc': - chart.menu = chart.type; - if(parts.length > 2 && parts[1] === 'dhcpd') - chart.menu_pattern = tmp + '_' + parts[1]; - else if(parts.length > 1) - chart.menu_pattern = tmp; - break; - - case 'ovpn': - chart.menu = chart.type; - if(parts.length > 3 && parts[1] === 'status' && parts[2] === 'log') - chart.menu_pattern = tmp + '_' + parts[1]; - else if(parts.length > 1) - chart.menu_pattern = tmp; - break; - - case 'smartd': - case 'web': - chart.menu = chart.type; - if(parts.length > 2 && parts[1] === 'log') - chart.menu_pattern = tmp + '_' + parts[1]; - else if(parts.length > 1) - 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(chart.context === 'tc.qos' && (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); - else - options.submenu_names[chart.family] = n; - } - - // increase the priority of IFB devices - // to have inbound appear before outbound - if(chart.id.match(/.*-ifb$/)) - chart.priority--; - - break; - - default: - chart.menu = chart.type; - if(parts.length > 1) - chart.menu_pattern = tmp; - break; - } - - chart.submenu = chart.family; - } - - // ---------------------------------------------------------------------------- - - function headMain(os, charts, duration) { - void(os); - - if(urlOptions.mode === 'print') - return ''; - - var head = ''; - - if(typeof charts['system.swap'] !== 'undefined') - head += '<div class="netdata-container" 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="9%"' - + ' 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 class="netdata-container" style="margin-right: 10px;" data-netdata="system.io"' - + ' data-dimensions="in"' - + ' data-chart-library="easypiechart"' - + ' data-title="Disk Read"' - + ' data-width="11%"' - + ' data-before="0"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-common-units="system.io.mainhead"' - + ' role="application"></div>'; - - head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.io"' - + ' data-dimensions="out"' - + ' data-chart-library="easypiechart"' - + ' data-title="Disk Write"' - + ' data-width="11%"' - + ' data-before="0"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-common-units="system.io.mainhead"' - + ' role="application"></div>'; - } - else if(typeof charts['system.pgpgio'] !== 'undefined') { - head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.pgpgio"' - + ' data-dimensions="in"' - + ' data-chart-library="easypiechart"' - + ' data-title="Disk Read"' - + ' data-width="11%"' - + ' data-before="0"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-common-units="system.pgpgio.mainhead"' - + ' role="application"></div>'; - - head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.pgpgio"' - + ' data-dimensions="out"' - + ' data-chart-library="easypiechart"' - + ' data-title="Disk Write"' - + ' data-width="11%"' - + ' data-before="0"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-common-units="system.pgpgio.mainhead"' - + ' role="application"></div>'; - } - - if(typeof charts['system.cpu'] !== 'undefined') - head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.cpu"' - + ' data-chart-library="gauge"' - + ' data-title="CPU"' - + ' data-units="%"' - + ' data-gauge-max-value="100"' - + ' data-width="20%"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-colors="' + NETDATA.colors[12] + '"' - + ' role="application"></div>'; - - if(typeof charts['system.net'] !== 'undefined') { - head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.net"' - + ' data-dimensions="received"' - + ' data-chart-library="easypiechart"' - + ' data-title="Net Inbound"' - + ' data-width="11%"' - + ' data-before="0"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-common-units="system.net.mainhead"' - + ' role="application"></div>'; - - head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.net"' - + ' data-dimensions="sent"' - + ' data-chart-library="easypiechart"' - + ' data-title="Net Outbound"' - + ' data-width="11%"' - + ' data-before="0"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-common-units="system.net.mainhead"' - + ' role="application"></div>'; - } - else if(typeof charts['system.ip'] !== 'undefined') { - head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ip"' - + ' data-dimensions="received"' - + ' data-chart-library="easypiechart"' - + ' data-title="IP Inbound"' - + ' data-width="11%"' - + ' data-before="0"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-common-units="system.ip.mainhead"' - + ' role="application"></div>'; - - head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ip"' - + ' data-dimensions="sent"' - + ' data-chart-library="easypiechart"' - + ' data-title="IP Outbound"' - + ' data-width="11%"' - + ' data-before="0"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-common-units="system.ip.mainhead"' - + ' role="application"></div>'; - } - else if(typeof charts['system.ipv4'] !== 'undefined') { - head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ipv4"' - + ' data-dimensions="received"' - + ' data-chart-library="easypiechart"' - + ' data-title="IPv4 Inbound"' - + ' data-width="11%"' - + ' data-before="0"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-common-units="system.ipv4.mainhead"' - + ' role="application"></div>'; - - head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ipv4"' - + ' data-dimensions="sent"' - + ' data-chart-library="easypiechart"' - + ' data-title="IPv4 Outbound"' - + ' data-width="11%"' - + ' data-before="0"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-common-units="system.ipv4.mainhead"' - + ' role="application"></div>'; - } - else if(typeof charts['system.ipv6'] !== 'undefined') { - head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ipv6"' - + ' data-dimensions="received"' - + ' data-chart-library="easypiechart"' - + ' data-title="IPv6 Inbound"' - + ' data-units="kbps"' - + ' data-width="11%"' - + ' data-before="0"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-common-units="system.ipv6.mainhead"' - + ' role="application"></div>'; - - head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ipv6"' - + ' data-dimensions="sent"' - + ' data-chart-library="easypiechart"' - + ' data-title="IPv6 Outbound"' - + ' data-units="kbps"' - + ' data-width="11%"' - + ' data-before="0"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-common-units="system.ipv6.mainhead"' - + ' role="application"></div>'; - } - - if(typeof charts['system.ram'] !== 'undefined') - head += '<div class="netdata-container" 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="9%"' - + ' data-after="-' + duration.toString() + '"' - + ' data-points="' + duration.toString() + '"' - + ' data-colors="' + NETDATA.colors[7] + '"' - + ' role="application"></div>'; - - return head; - } - - function generateHeadCharts(type, chart, duration) { - if(urlOptions.mode === 'print') - return ''; - - 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](netdataDashboard.os, chart.id).replace(/CHART_DURATION/g, duration.toString()).replace(/CHART_UNIQUE_ID/g, chart.id); - else - head += hcharts[hi].replace(/CHART_DURATION/g, duration.toString()).replace(/CHART_UNIQUE_ID/g, chart.id); - hi++; - } - } - return head; - } - - function renderPage(menus, data) { - var div = document.getElementById('charts_div'); - var pcent_width = Math.floor(100 / chartsPerRow($(div).width())); - - // find the proper duration for per-second updates - var duration = Math.round(($(div).width() * pcent_width / 100 * data.update_every / 3) / 60) * 60; - options.duration = duration; - options.update_every = data.update_every; - - var html = ''; - var sidebar = '<ul class="nav dashboard-sidenav" data-spy="affix" id="sidebar_ul">'; - var mainhead = headMain(netdataDashboard.os, 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" class="dashboard-section"><div role="sectionhead"><h1 id="' + menuid + '" role="heading">' + menus[menu].icon + ' ' + menus[menu].title + '</h1></div><div role="section" class="dashboard-subsection">'; - - 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 role="section" class="dashboard-section-container" id="' + submenuid + '"><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="dashboard-submenu-info 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); - - function chartCommonMin(family, context, units) { - var x = netdataDashboard.anyAttribute(netdataDashboard.context, 'commonMin', context, undefined); - if(typeof x !== 'undefined') - return ' data-common-min="' + family + '/' + context + '/' + units + '"'; - else - return ''; - } - - function chartCommonMax(family, context, units) { - var x = netdataDashboard.anyAttribute(netdataDashboard.context, 'commonMax', context, undefined); - if(typeof x !== 'undefined') - return ' data-common-max="' + family + '/' + context + '/' + units + '"'; - else - return ''; - } - - // generate the chart - if(urlOptions.mode === 'print') - chtml += '<div role="row" class="dashboard-print-row">'; - - chtml += '<div class="netdata-chartblock-container" style="width: ' + pcent_width.toString() + '%;">' + netdataDashboard.contextInfo(chart.context) + '<div class="netdata-container" id="chart_' + NETDATA.name2id(chart.id) + '" data-netdata="' + chart.id + '"' - + ' data-width="100%"' - + ' 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, '') + '"' - + ' data-decimal-digits="' + netdataDashboard.contextDecimalDigits(chart.context, -1) + '"' - + chartCommonMin(chart.family, chart.context, chart.units) - + chartCommonMax(chart.family, chart.context, chart.units) - + ' role="application"></div></div>'; - - if(urlOptions.mode === 'print') - chtml += '</div>'; - - // console.log(' \------- ' + chart.id + ' (' + chart.priority + '): ' + chart.context + ' height: ' + menus[menu].submenus[submenu].height); - } - - head += '</div>'; - shtml += head + chtml + '</div>'; - } - - mhead += '</div>'; - sidebar += '</ul></li>'; - html += mhead + shtml + '</div></div><hr role="separator"/>'; - } - - sidebar += '<li class="" style="padding-top:15px;"><a href="https://github.com/netdata/netdata/wiki/Add-more-charts-to-netdata" target="_blank"><i class="fas fa-plus"></i> add more charts</a></li>'; - sidebar += '<li class=""><a href="https://github.com/netdata/netdata/wiki/Add-more-alarms-to-netdata" target="_blank"><i class="fas fa-plus"></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 ' + NETDATA.seconds4human(data.update_every * data.history, { space: ' ' }) + ' of real-time history.<br/> <br/><b>netdata</b><br/>v' + data.version.toString() +'</small></li>'; - sidebar += '</ul>'; - div.innerHTML = html; - document.getElementById('sidebar').innerHTML = sidebar; - - if(urlOptions.highlight === true) - NETDATA.globalChartUnderlay.init(null - , urlOptions.highlight_after - , urlOptions.highlight_before - , (urlOptions.after > 0) ? urlOptions.after : null - , (urlOptions.before > 0) ? urlOptions.before : null - ); - else - NETDATA.globalChartUnderlay.clear(); - - if(urlOptions.mode === 'print') - printPage(); - else - finalizePage(); - } - - function renderChartsAndMenu(data) { - options.menus = {}; - options.submenu_names = {}; - - var menus = options.menus; - var charts = data.charts; - var m, menu_key; - - for(var c in charts) { - if(!charts.hasOwnProperty(c)) continue; - - var chart = charts[c]; - enrichChartData(chart); - m = chart.menu; - - // create the menu - if(typeof menus[m] === 'undefined') { - menus[m] = { - menu_pattern: chart.menu_pattern, - priority: chart.priority, - submenus: {}, - title: netdataDashboard.menuTitle(chart), - icon: netdataDashboard.menuIcon(chart), - info: netdataDashboard.menuInfo(chart), - height: netdataDashboard.menuHeight(chart) * options.chartsHeight - }; - } - else { - if(typeof(menus[m].menu_pattern) === 'undefined') - menus[m].menu_pattern = chart.menu_pattern; - - if(chart.priority < menus[m].priority) - menus[m].priority = chart.priority; - } - - menu_key = (typeof(menus[m].menu_pattern) !== 'undefined')?menus[m].menu_pattern:m; - - // create the submenu - if(typeof menus[m].submenus[chart.submenu] === 'undefined') { - menus[m].submenus[chart.submenu] = { - priority: chart.priority, - charts: [], - title: null, - info: netdataDashboard.submenuInfo(menu_key, chart.submenu), - height: netdataDashboard.submenuHeight(menu_key, chart.submenu, menus[m].height) - }; - } - else { - if (chart.priority < menus[m].submenus[chart.submenu].priority) - menus[m].submenus[chart.submenu].priority = chart.priority; - } - - // index the chart in the menu/submenu - menus[m].submenus[chart.submenu].charts.push(chart); - } - - // propagate the descriptive subname given to QoS - // to all the other submenus with the same name - for(m in menus) { - if(!menus.hasOwnProperty(m)) continue; - - for(var s in menus[m].submenus) { - if(!menus[m].submenus.hasOwnProperty(s)) continue; - - // set the family using a name - if(typeof options.submenu_names[s] !== 'undefined') { - menus[m].submenus[s].title = s + ' (' + options.submenu_names[s] + ')'; - } - else { - menu_key = (typeof(menus[m].menu_pattern) !== 'undefined')?menus[m].menu_pattern:m; - menus[m].submenus[s].title = netdataDashboard.submenuTitle(menu_key, s); - } - } - } - - renderPage(menus, data); - } - - // ---------------------------------------------------------------------------- - - function loadJs(url, callback) { - $.ajax({ - url: url, - cache: true, - dataType: "script", - xhrFields: { withCredentials: true } // required for the cookie - }) - .fail(function() { - alert('Cannot load required JS library: ' + url); - }) - .always(function() { - if(typeof callback === 'function') - callback(); - }) - } - - var clipboardLoaded = false; - function loadClipboard(callback) { - if(clipboardLoaded === false) { - clipboardLoaded = true; - loadJs('lib/clipboard-polyfill-be05dad.js', callback); - } - else callback(); - } - - var bootstrapTableLoaded = false; - function loadBootstrapTable(callback) { - if(bootstrapTableLoaded === false) { - bootstrapTableLoaded = true; - loadJs('lib/bootstrap-table-1.11.0.min.js', function() { - loadJs('lib/bootstrap-table-export-1.11.0.min.js', function() { - loadJs('lib/tableExport-1.6.0.min.js', callback); - }) - }); - } - else callback(); - } - - var bootstrapSliderLoaded = false; - function loadBootstrapSlider(callback) { - if(bootstrapSliderLoaded === false) { - bootstrapSliderLoaded = true; - loadJs('lib/bootstrap-slider-10.0.0.min.js', function() { - NETDATA._loadCSS('css/bootstrap-slider-10.0.0.min.css'); - callback(); - }); - } - else callback(); - } - - var lzStringLoaded = false; - function loadLzString(callback) { - if(lzStringLoaded === false) { - lzStringLoaded = true; - loadJs('lib/lz-string-1.4.4.min.js', callback); - } - else callback(); - } - - var pakoLoaded = false; - function loadPako(callback) { - if(pakoLoaded === false) { - pakoLoaded = true; - loadJs('lib/pako-1.0.6.min.js', callback); - } - else callback(); - } - - // ---------------------------------------------------------------------------- - - function clipboardCopy(text) { - clipboard.writeText(text); - } - function clipboardCopyBadgeEmbed(url) { - clipboard.writeText('<embed src="' + url + '" type="image/svg+xml" height="20"/>'); - } - - - // ---------------------------------------------------------------------------- - - 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/netdata/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/netdata/netdata/blob/master/conf.d/health_alarm_notify.conf">this configuration file</a> for more information.'; - - loadClipboard(function() {}); - - NETDATA.alarms.get('all', function(data) { - options.alarm_families = []; - - alarmsCallback(data); - - if(data === null) { - document.getElementById('alarms_active').innerHTML = - document.getElementById('alarms_all').innerHTML = - document.getElementById('alarms_log').innerHTML = - 'failed to load alarm data!'; - return; - } - - function alarmid4human(id) { - if(id === 0) - return '-'; - - return id.toString(); - } - - function timestamp4human(timestamp, space) { - if(timestamp === 0) - return '-'; - - if(typeof space === 'undefined') - space = ' '; - - var t = new Date(timestamp * 1000); - var now = new Date(); - - if(t.toDateString() === now.toDateString()) - return t.toLocaleTimeString(); - - return t.toLocaleDateString() + space + t.toLocaleTimeString(); - } - - function alarm_lookup_explain(alarm, chart) { - var dimensions = ' of all values '; - - if(chart.dimensions.length > 1) - dimensions = ' of the sum of all dimensions '; - - if(typeof alarm.lookup_dimensions !== 'undefined') { - var d = alarm.lookup_dimensions.replace(/|/g, ','); - var x = d.split(','); - if(x.length > 1) - dimensions = 'of the sum of dimensions <code>' + alarm.lookup_dimensions + '</code> '; - else - dimensions = 'of all values of dimension <code>' + alarm.lookup_dimensions + '</code> '; - } - - return '<code>' + alarm.lookup_method + '</code> ' - + dimensions + ', of chart <code>' + alarm.chart + '</code>' - + ', starting <code>' + NETDATA.seconds4human(alarm.lookup_after + alarm.lookup_before, { space: ' ' }) + '</code> and up to <code>' + NETDATA.seconds4human(alarm.lookup_before, { space: ' ' }) + '</code>' - + ((alarm.lookup_options)?(', with options <code>' + alarm.lookup_options.replace(/ /g, ', ') + '</code>'):'') - + '.'; - } - - function alarm_to_html(alarm, full) { - var chart = options.data.charts[alarm.chart]; - if(typeof(chart) === 'undefined') { - chart = options.data.charts_by_name[alarm.chart]; - if (typeof(chart) === 'undefined') { - // this means the charts loaded are incomplete - // probably netdata was restarted and more alarms - // are now available. - console.log('Cannot find chart ' + alarm.chart + ', you probably need to refresh the page.'); - return ''; - } - } - - var has_alarm = (typeof alarm.warn !== 'undefined' || typeof alarm.crit !== 'undefined'); - var badge_url = NETDATA.alarms.server + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto'; - - var action_buttons = '<br/> <br/>role: <b>' + alarm.recipient + '</b><br/> <br/>' - + '<div class="action-button ripple" title="click to scroll the dashboard to the chart of this alarm" data-toggle="tooltip" data-placement="bottom" onClick="scrollToChartAfterHidingModal(\'' + alarm.chart + '\'); $(\'#alarmsModal\').modal(\'hide\'); return false;"><i class="fab fa-periscope"></i></div>' - + '<div class="action-button ripple" title="click to copy to the clipboard the URL of this badge" data-toggle="tooltip" data-placement="bottom" onClick="clipboardCopy(\'' + badge_url + '\'); return false;"><i class="far fa-copy"></i></div>' - + '<div class="action-button ripple" title="click to copy to the clipboard an auto-refreshing <code>embed</code> html element for this badge" data-toggle="tooltip" data-placement="bottom" onClick="clipboardCopyBadgeEmbed(\'' + badge_url + '\'); return false;"><i class="fas fa-copy"></i></div>'; - - var html = '<tr><td class="text-center" style="vertical-align:middle" width="40%"><b>' + alarm.chart + '</b><br/> <br/><embed src="' + badge_url + '" type="image/svg+xml" height="20"/><br/> <br/><span style="font-size: 18px">' + alarm.info + '</span>' + action_buttons + '</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) { - var units = chart.units; - if(units === '%') units = '%'; - - 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 + ' ' + units + '</code></td></tr>'):'') - + ((chart.red !== null)?('<tr><td width="10%" style="text-align:right">red threshold</td><td><code>' + chart.red + ' ' + units + '</code></td></tr>'):''); - } - - var delay = ''; - if((alarm.delay_up_duration > 0 || alarm.delay_down_duration > 0) && alarm.delay_multiplier !== 0 && alarm.delay_max_duration > 0) { - if(alarm.delay_up_duration === alarm.delay_down_duration) { - delay += '<small><br/>hysteresis ' + NETDATA.seconds4human(alarm.delay_up_duration, { space: ' ', negative_suffix: '' }); - } - else { - delay = '<small><br/>hysteresis '; - if(alarm.delay_up_duration > 0) { - delay += 'on escalation <code>' + NETDATA.seconds4human(alarm.delay_up_duration, { space: ' ', negative_suffix: '' }) + '</code>, '; - } - if(alarm.delay_down_duration > 0) { - delay += 'on recovery <code>' + NETDATA.seconds4human(alarm.delay_down_duration, { space: ' ', negative_suffix: '' }) + '</code>, '; - } - } - if(alarm.delay_multiplier !== 1.0) { - delay += 'multiplied by <code>' + alarm.delay_multiplier.toString() + '</code>'; - delay += ', up to <code>' + NETDATA.seconds4human(alarm.delay_max_duration, { space: ' ', negative_suffix: '' }) + '</code>'; - } - delay += '</small>'; - } - - html += '<tr><td width="10%" style="text-align:right">check every</td><td>' + NETDATA.seconds4human(alarm.update_every, { space: ' ', 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>'; - - return html; - } - - function alarm_family_show(id) { - var html = '<table class="table">'; - var family = options.alarm_families[id]; - var len = family.arr.length; - while(len--) { - var alarm = family.arr[len]; - html += alarm_to_html(alarm, true); - } - html += '</table>'; - - $('#alarm_all_' + id.toString()).html(html); - enableTooltipsAndPopovers(); - } - - // find the proper family of each alarm - var x, family, alarm; - var count_active = 0; - var count_all = 0; - var families = {}; - var families_sort = []; - for(x in data.alarms) { - if(!data.alarms.hasOwnProperty(x)) continue; - - alarm = data.alarms[x]; - 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: [], - priority: chart.priority - }; - - families_sort.push(families[family]); - } - - if(chart.priority < families[family].priority) - families[family].priority = chart.priority; - - families[family].arr.unshift(alarm); - } - - // sort the families, like the dashboard menu does - var families_sorted = families_sort.sort(function (a, b) { - if (a.priority < b.priority) return -1; - if (a.priority > b.priority) return 1; - return naturalSortCompare(a.name, b.name); - }); - - var i = 0; - var fc = 0; - var len = families_sorted.length; - while(len--) { - family = families_sorted[i++].name; - var active_family_added = false; - var expanded = 'true'; - var collapsed = ''; - var cin = 'in'; - - if(fc !== 0) { - all += "</table></div></div></div>"; - expanded = 'false'; - collapsed = 'class="collapsed"'; - cin = ''; - } - - all += '<div class="panel panel-default"><div class="panel-heading" role="tab" id="alarm_all_heading_' + fc.toString() + '"><h4 class="panel-title"><a ' + collapsed + ' role="button" data-toggle="collapse" data-parent="#alarms_all_accordion" href="#alarm_all_' + fc.toString() + '" aria-expanded="' + expanded + '" aria-controls="alarm_all_' + fc.toString() + '">' + family.toString() + '</a></h4></div><div id="alarm_all_' + fc.toString() + '" class="panel-collapse collapse ' + cin + '" role="tabpanel" aria-labelledby="alarm_all_heading_' + fc.toString() + '" data-alarm-id="' + fc.toString() + '"><div class="panel-body" id="alarm_all_body_' + fc.toString() + '">'; - - options.alarm_families[fc] = families[family]; - - fc++; - - var arr = families[family].arr; - var c = arr.length; - while(c--) { - alarm = arr[c]; - if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') { - if(!active_family_added) { - active_family_added = true; - active += '<tr><th class="text-center" colspan="2"><h4>' + family + '</h4></th></tr>'; - } - count_active++; - active += alarm_to_html(alarm, true); - } - - count_all++; - } - } - active += "</table>"; - if(families_sorted.length > 0) all += "</div></div></div>"; - all += "</div>"; - - if(!count_active) - active += '<div style="width:100%; height: 100px; text-align: center;"><span style="font-size: 50px;"><i class="fas fa-thumbs-up"></i></span><br/>Everything is normal. No raised alarms.</div>'; - else - active += footer; - - if(!count_all) - all += "<h4>No alarms are running in this system.</h4>"; - else - all += footer; - - document.getElementById('alarms_active').innerHTML = active; - document.getElementById('alarms_all').innerHTML = all; - enableTooltipsAndPopovers(); - - if(families_sorted.length > 0) alarm_family_show(0); - - // register bootstrap events - var $accordion = $('#alarms_all_accordion'); - $accordion.on('show.bs.collapse', function (d) { - var target = $(d.target); - var id = $(target).data('alarm-id'); - alarm_family_show(id); - }); - $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) { - void(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', - formatter: function(value, row, index) { void(row); void(index); return timestamp4human(value, ' '); }, - align: 'center', - switchable: false, - sortable: true - }, - { - field: 'hostname', - title: 'Host', - valign: 'middle', - titleTooltip: 'The host that generated this event', - align: 'center', - visible: false, - sortable: true - }, - { - field: 'unique_id', - title: 'Unique ID', - titleTooltip: 'The host unique ID for this event', - formatter: function(value, row, index) { void(row); void(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) { void(row); void(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) { void(row); void(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) { - void(row); - void(index); - return value.toString().replace(/_/g, ' '); - }, - align: 'center', - valign: 'middle', - switchable: false, - sortable: true - }, - { - field: 'value_string', - title: 'Friendly Value', - titleTooltip: 'The value of the alarm, that triggered this event', - align: 'right', - valign: 'middle', - sortable: true - }, - { - field: 'old_value_string', - title: 'Friendly Old Value', - titleTooltip: 'The value of the alarm, just before this event', - align: 'right', - valign: 'middle', - visible: false, - sortable: true - }, - { - field: 'old_value', - title: 'Old Value', - titleTooltip: 'The value of the alarm, just before this event', - formatter: function(value, row, index) { - void(row); - void(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) { - void(row); - void(index); - return ((value !== null)?Math.round(value * 100) / 100:'NaN').toString(); - }, - align: 'right', - valign: 'middle', - visible: false, - sortable: true - }, - { - field: 'units', - title: 'Units', - titleTooltip: 'The units of the value of the alarm', - align: 'left', - valign: 'middle', - visible: false, - 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) { - void(row); - void(index); - return NETDATA.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) { - void(row); - void(index); - return NETDATA.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) { - void(row); - void(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) { - void(row); - void(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) { void(row); void(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) { void(row); void(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) { void(row); void(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) { - void(row); - void(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) { - void(row); - void(index); - - return NETDATA.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) { void(row); void(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')); - }); - }); - } - - function alarmsCallback(data) { - var count = 0, x; - for(x in data.alarms) { - if(!data.alarms.hasOwnProperty(x)) continue; - - var alarm = data.alarms[x]; - if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') - count++; - } - - if(count > 0) - document.getElementById('alarms_count_badge').innerHTML = count.toString(); - else - document.getElementById('alarms_count_badge').innerHTML = ''; - } - - function initializeDynamicDashboardWithData(data) { - if(data !== null) { - options.hostname = data.hostname; - options.data = data; - options.version = data.version; - netdataDashboard.os = data.os; - - if(typeof data.hosts !=='undefined') - options.hosts = data.hosts; - - // update the dashboard hostname - document.getElementById('hostname').innerHTML = options.hostname + ((netdataSnapshotData !== null)?' (snap)':'').toString(); - document.getElementById('hostname').href = NETDATA.serverDefault; - document.getElementById('netdataVersion').innerHTML = options.version; - - if(netdataSnapshotData !== null) { - $('#alarmsButton').hide(); - $('#updateButton').hide(); - // $('#loadButton').hide(); - $('#saveButton').hide(); - $('#printButton').hide(); - } - - // 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) { - if(!charts.hasOwnProperty(x)) continue; - - var chart = charts[x]; - data.charts_by_name[chart.name] = chart; - } - - // render all charts - renderChartsAndMenu(data); - } - } - - // an object to keep initilization configuration - // needed due to the async nature of the XSS modal - var initializeConfig = { - url: null, - custom_info: true, - }; - - function loadCustomDashboardInfo(url, callback) { - loadJs(url, function () { - $.extend(true, netdataDashboard, customDashboard); - callback(); - }); - } - - function initializeChartsAndCustomInfo() { - NETDATA.alarms.callback = alarmsCallback; - - // download all the charts the server knows - NETDATA.chartRegistry.downloadAll(initializeConfig.url, function(data) { - if(data !== null) { - if (initializeConfig.custom_info === true && typeof data.custom_info !== 'undefined' && data.custom_info !== "" && netdataSnapshotData === null) { - //console.log('loading custom dashboard decorations from server ' + initializeConfig.url); - loadCustomDashboardInfo(NETDATA.serverDefault + data.custom_info, function () { - initializeDynamicDashboardWithData(data); - }); - } - else { - //console.log('not loading custom dashboard decorations from server ' + initializeConfig.url); - initializeDynamicDashboardWithData(data); - } - } - }); - } - - function xssModalDisableXss() { - //console.log('disabling xss checks'); - NETDATA.xss.enabled = false; - NETDATA.xss.enabled_for_data = false; - initializeConfig.custom_info = true; - initializeChartsAndCustomInfo(); - return false; - } - - function xssModalKeepXss() { - //console.log('keeping xss checks'); - NETDATA.xss.enabled = true; - NETDATA.xss.enabled_for_data = true; - initializeConfig.custom_info = false; - initializeChartsAndCustomInfo(); - return false; - } - - function initializeDynamicDashboard(netdata_url) { - if(typeof netdata_url === 'undefined' || netdata_url === null) - netdata_url = NETDATA.serverDefault; - - initializeConfig.url = netdata_url; - - // initialize clickable alarms - NETDATA.alarms.chart_div_offset = -50; - NETDATA.alarms.chart_div_id_prefix = 'chart_'; - NETDATA.alarms.chart_div_animation_duration = 0; - - NETDATA.pause(function() { - if(typeof netdataCheckXSS !== 'undefined' && netdataCheckXSS === true) { - //$("#loadOverlay").css("display","none"); - document.getElementById('netdataXssModalServer').innerText = initializeConfig.url; - $('#xssModal').modal('show'); - } - else { - initializeChartsAndCustomInfo(); - } - }); - } - - // ---------------------------------------------------------------------------- - - function versionLog(msg) { - document.getElementById('versionCheckLog').innerHTML = msg; - } - - function getNetdataCommitIdFromVersion() { - var s = options.version.split('-'); - - if(s.length !== 3) return null; - if(s[2][0] === 'g') { - var v = s[2].split('_')[0].substring(1, 8); - if(v.length === 7) { - versionLog('Installed git commit id of netdata is ' + v); - document.getElementById('netdataCommitId').innerHTML = v; - return v; - } - } - return null; - } - - function getNetdataCommitId(force, callback) { - versionLog('Downloading installed git commit id 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,""); - - var c = getNetdataCommitIdFromVersion(); - if(c !== null && data.length === 40 && data.substring(0, 7) !== c) { - versionLog('Installed files commit id and internal netdata git commit id do not match'); - data = c; - } - - if(data.length >= 7) { - versionLog('Installed git commit id of netdata is ' + data); - document.getElementById('netdataCommitId').innerHTML = data.substring(0, 7); - callback(data); - } - }) - .fail(function() { - versionLog('Failed to download installed git commit id from netdata!'); - - if(force === true) { - var c = getNetdataCommitIdFromVersion(); - if(c === null) versionLog('Cannot find the git commit id of netdata.'); - callback(c); - } - else - callback(null); - }); - } - - function getGithubLatestCommit(callback) { - versionLog('Downloading latest git commit id info from github...'); - - $.ajax({ - url: 'https://api.github.com/repos/netdata/netdata/commits', - async: true, - cache: false - }) - .done(function(data) { - versionLog('Latest git commit id from github is ' + data[0].sha); - callback(data[0].sha); - }) - .fail(function() { - versionLog('Failed to download installed git commit id from github!'); - callback(null); - }); - } - - function checkForUpdate(force, callback) { - getNetdataCommitId(force, function(sha1) { - if(sha1 === null) callback(null, null); - - getGithubLatestCommit(function(sha2) { - callback(sha1, sha2); - }); - }); - - return null; - } - - function notifyForUpdate(force) { - versionLog('<p>checking for updates...</p>'); - - var now = Date.now(); - - if(typeof force === 'undefined' || force !== true) { - var last = loadLocalStorage('last_update_check'); - - if(typeof last === 'string') - last = parseInt(last); - else - last = 0; - - if(now - last < 3600000 * 8) { - // no need to check it - too soon - return; - } - } - - checkForUpdate(force, function(sha1, sha2) { - var save = false; - - if(sha1 === null) { - save = false; - versionLog('<p><big>Failed to get your netdata git commit id!</big></p><p>You can always get the latest netdata from <a href="https://github.com/netdata/netdata" target="_blank">its github page</a>.</p>'); - } - else if(sha2 === null) { - save = false; - versionLog('<p><big>Failed to get the latest git commit id from github.</big></p><p>You can always get the latest netdata from <a href="https://github.com/netdata/netdata" target="_blank">its github page</a>.</p>'); - } - else if(sha1 === sha2) { - save = true; - versionLog('<p><big>You already have the latest netdata!</big></p><p>No update yet?<br/>Probably, we need some motivation to keep going on!</p><p>If you haven\'t already, <a href="https://github.com/netdata/netdata" target="_blank">give netdata a <b><i class="fas fa-star"></i></b> at its github page</a>.</p>'); - } - else { - save = true; - var compare = 'https://github.com/netdata/netdata/compare/' + sha1.toString() + '...' + sha2.toString(); - - versionLog('<p><big><strong>New version of netdata available!</strong></big></p><p>Latest commit: <b><code>' + sha2.substring(0, 7).toString() + '</code></b></p><p><a href="' + compare + '" target="_blank">Click here for the changes log</a> since your installed version, and<br/><a href="https://github.com/netdata/netdata/wiki/Updating-Netdata" target="_blank">click here for directions on updating</a> your netdata installation.</p><p>We suggest to review the changes log for new features you may be interested, or important bug fixes you may need.<br/>Keeping your netdata updated, is generally a good idea.</p>'); - - document.getElementById('update_badge').innerHTML = '!'; - } - - if(save) - saveLocalStorage('last_update_check', now.toString()); - }); - } - - // ---------------------------------------------------------------------------- - // printing dashboards - - function showPageFooter() { - document.getElementById('footer').style.display = 'block'; - } - - - function printPreflight() { - var url = document.location.origin.toString() + document.location.pathname.toString() + document.location.search.toString() + urlOptions.genHash() + ';mode=print'; - var width = 990; - var height = screen.height * 90 / 100; - //console.log(url); - //console.log(document.location); - window.open(url, '', 'width=' + width.toString() + ',height=' + height.toString() + ',menubar=no,toolbar=no,personalbar=no,location=no,resizable=no,scrollbars=yes,status=no,chrome=yes,centerscreen=yes,attention=yes,dialog=yes'); - $('#printPreflightModal').modal('hide'); - } - - function printPage() { - var print_is_rendering = true; - - $('#printModal').on('hide.bs.modal', function(e) { - if(print_is_rendering === true) { - e.preventDefault(); - return false; - } - - return true; - }); - - $('#printModal').on('show.bs.modal', function() { - var print_options = { - stop_updates_when_focus_is_lost: false, - update_only_visible: false, - sync_selection: false, - eliminate_zero_dimensions: false, - pan_and_zoom_data_padding: false, - show_help: false, - legend_toolbox: false, - resize_charts: false, - pixels_per_point: 1 - }; - - var x; - for(x in print_options) { - if (print_options.hasOwnProperty(x)) - NETDATA.options.current[x] = print_options[x]; - } - - NETDATA.parseDom(); - showPageFooter(); - - NETDATA.globalSelectionSync.stop(); - NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before); - // NETDATA.onresize(); - - var el = document.getElementById('printModalProgressBar'); - var eltxt = document.getElementById('printModalProgressBarText'); - - function update_chart(idx) { - var state = NETDATA.options.targets[--idx]; - - var pcent = (NETDATA.options.targets.length - idx) * 100 / NETDATA.options.targets.length; - $(el).css('width', pcent+'%').attr('aria-valuenow', pcent); - eltxt.innerText = Math.round(pcent).toString() + '%, ' + state.id; - - setTimeout(function() { - state.updateChart(function () { - NETDATA.options.targets[idx].resizeForPrint(); - - if (idx > 0) { - update_chart(idx); - } - else { - print_is_rendering = false; - $('#printModal').modal('hide'); - window.print(); - window.close(); - } - }) - }, 0); - } - - print_is_rendering = true; - update_chart(NETDATA.options.targets.length); - }); - - $('#printModal').modal('show'); - } - - // -------------------------------------------------------------------- - - function jsonStringifyFn(obj) { - return JSON.stringify(obj, function (key, value) { - return (typeof value === 'function' ) ? value.toString() : value; - }); - } - - function jsonParseFn(str) { - return JSON.parse(str, function (key, value) { - if (typeof value != 'string') return value; - return ( value.substring(0, 8) == 'function') ? eval('(' + value + ')') : value; - }); - } - - // -------------------------------------------------------------------- - - var snapshotOptions = { - bytes_per_chart: 2048, - compressionDefault: 'pako.deflate.base64', - - compressions: { - 'none': { - bytes_per_point_memory: 5.2, - bytes_per_point_disk: 5.6, - - compress: function (s) { - return s; - }, - - compressed_length: function (s) { - return s.length; - }, - - uncompress: function (s) { - return s; - } - }, - - 'pako.deflate.base64': { - bytes_per_point_memory: 1.8, - bytes_per_point_disk: 1.9, - - compress: function (s) { - return btoa(pako.deflate(s, { to: 'string' })); - }, - - compressed_length: function (s) { - return s.length; - }, - - uncompress: function (s) { - return pako.inflate(atob(s), {to: 'string'}); - } - }, - - 'pako.deflate': { - bytes_per_point_memory: 1.4, - bytes_per_point_disk: 3.2, - - compress: function (s) { - return pako.deflate(s, { to: 'string' }); - }, - - compressed_length: function (s) { - return s.length; - }, - - uncompress: function (s) { - return pako.inflate(s, {to: 'string'}); - } - }, - - 'lzstring.utf16': { - bytes_per_point_memory: 1.7, - bytes_per_point_disk: 2.6, - - compress: function (s) { - return LZString.compressToUTF16(s); - }, - - compressed_length: function (s) { - return s.length * 2; - }, - - uncompress: function (s) { - return LZString.decompressFromUTF16(s); - } - }, - - 'lzstring.base64': { - bytes_per_point_memory: 2.1, - bytes_per_point_disk: 2.3, - - compress: function (s) { - return LZString.compressToBase64(s); - }, - - compressed_length: function (s) { - return s.length; - }, - - uncompress: function (s) { - return LZString.decompressFromBase64(s); - } - }, - - 'lzstring.uri': { - bytes_per_point_memory: 2.1, - bytes_per_point_disk: 2.3, - - compress: function (s) { - return LZString.compressToEncodedURIComponent(s); - }, - - compressed_length: function (s) { - return s.length; - }, - - uncompress: function (s) { - return LZString.decompressFromEncodedURIComponent(s); - } - } - } - }; - - // -------------------------------------------------------------------- - // loading snapshots - - function loadSnapshotModalLog(priority, msg) { - document.getElementById('loadSnapshotStatus').className = "alert alert-" + priority; - document.getElementById('loadSnapshotStatus').innerHTML = msg; - } - - var tmpSnapshotData = null; - function loadSnapshot() { - $('#loadSnapshotImport').addClass('disabled'); - - if(tmpSnapshotData === null) { - loadSnapshotPreflightEmpty(); - loadSnapshotModalLog('danger', 'no data have been loaded'); - return; - } - - loadPako(function() { - loadLzString(function () { - loadSnapshotModalLog('info', 'Please wait, activating snapshot...'); - $('#loadSnapshotModal').modal('hide'); - - netdataShowAlarms = false; - netdataRegistry = false; - netdataServer = tmpSnapshotData.server; - NETDATA.serverDefault = netdataServer; - - document.getElementById('charts_div').innerHTML = ''; - document.getElementById('sidebar').innerHTML = ''; - NETDATA.globalReset(); - - if (typeof tmpSnapshotData.hash !== 'undefined') - urlOptions.hash = tmpSnapshotData.hash; - else - urlOptions.hash = '#'; - - if (typeof tmpSnapshotData.info !== 'undefined') { - var info = jsonParseFn(tmpSnapshotData.info); - if (typeof info.menu !== 'undefined') - netdataDashboard.menu = info.menu; - - if (typeof info.submenu !== 'undefined') - netdataDashboard.submenu = info.submenu; - - if (typeof info.context !== 'undefined') - netdataDashboard.context = info.context; - } - - if (typeof tmpSnapshotData.compression !== 'string') - tmpSnapshotData.compression = 'none'; - - if (typeof snapshotOptions.compressions[tmpSnapshotData.compression] === 'undefined') { - alert('unknown compression method: ' + tmpSnapshotData.compression); - tmpSnapshotData.compression = 'none'; - } - - tmpSnapshotData.uncompress = snapshotOptions.compressions[tmpSnapshotData.compression].uncompress; - netdataSnapshotData = tmpSnapshotData; - - urlOptions.after = tmpSnapshotData.after_ms; - urlOptions.before = tmpSnapshotData.before_ms; - - if( typeof tmpSnapshotData.highlight_after_ms !== 'undefined' - && tmpSnapshotData.highlight_after_ms !== null - && tmpSnapshotData.highlight_after_ms > 0 - && typeof tmpSnapshotData.highlight_before_ms !== 'undefined' - && tmpSnapshotData.highlight_before_ms !== null - && tmpSnapshotData.highlight_before_ms > 0 - ) { - urlOptions.highlight_after = tmpSnapshotData.highlight_after_ms; - urlOptions.highlight_before = tmpSnapshotData.highlight_before_ms; - urlOptions.highlight = true; - } - else { - urlOptions.highlight_after = 0; - urlOptions.highlight_before = 0; - urlOptions.highlight = false; - } - - netdataCheckXSS = false; // disable the modal - this does not affect XSS checks, since dashboard.js is already loaded - NETDATA.xss.enabled = true; // we should not do any remote requests, but if we do, check them - NETDATA.xss.enabled_for_data = true; // check also snapshot data - that have been excluded from the initial check, due to compression - loadSnapshotPreflightEmpty(); - initializeDynamicDashboard(); - }); - }); - }; - - - function loadSnapshotPreflightFile(file) { - var filename = NETDATA.xss.string(file.name); - var fr = new FileReader(); - fr.onload = function(e) { - document.getElementById('loadSnapshotFilename').innerHTML = filename; - var result = null; - try { - result = NETDATA.xss.checkAlways('snapshot', JSON.parse(e.target.result), /^(snapshot\.info|snapshot\.data)$/); - - //console.log(result); - var date_after = new Date(result.after_ms); - var date_before = new Date(result.before_ms); - - if (typeof result.charts_ok === 'undefined') - result.charts_ok = 'unknown'; - - if (typeof result.charts_failed === 'undefined') - result.charts_failed = 0; - - if (typeof result.compression === 'undefined') - result.compression = 'none'; - - if (typeof result.data_size === 'undefined') - result.data_size = 0; - - document.getElementById('loadSnapshotFilename').innerHTML = '<code>' + filename + '</code>'; - document.getElementById('loadSnapshotHostname').innerHTML = '<b>' + result.hostname + '</b>, netdata version: <b>' + result.netdata_version.toString() + '</b>'; - document.getElementById('loadSnapshotURL').innerHTML = result.url; - document.getElementById('loadSnapshotCharts').innerHTML = result.charts.charts_count.toString() + ' charts, ' + result.charts.dimensions_count.toString() + ' dimensions, ' + result.data_points.toString() + ' points per dimension, ' + Math.round(result.duration_ms / result.data_points).toString() + ' ms per point'; - document.getElementById('loadSnapshotInfo').innerHTML = 'version: <b>' + result.snapshot_version.toString() + '</b>, includes <b>' + result.charts_ok.toString() + '</b> unique chart data queries ' + ((result.charts_failed > 0) ? ('<b>' + result.charts_failed.toString() + '</b> failed') : '').toString() + ', compressed with <code>' + result.compression.toString() + '</code>, data size ' + (Math.round(result.data_size * 100 / 1024 / 1024) / 100).toString() + ' MB'; - document.getElementById('loadSnapshotTimeRange').innerHTML = '<b>' + NETDATA.dateTime.localeDateString(date_after) + ' ' + NETDATA.dateTime.localeTimeString(date_after) + '</b> to <b>' + NETDATA.dateTime.localeDateString(date_before) + ' ' + NETDATA.dateTime.localeTimeString(date_before) + '</b>'; - document.getElementById('loadSnapshotComments').innerHTML = ((result.comments) ? result.comments : '').toString(); - loadSnapshotModalLog('success', 'File loaded, click <b>Import</b> to render it!'); - $('#loadSnapshotImport').removeClass('disabled'); - - tmpSnapshotData = result; - } - catch (e) { - console.log(e); - document.getElementById('loadSnapshotStatus').className = "alert alert-danger"; - document.getElementById('loadSnapshotStatus').innerHTML = "Failed to parse this file!"; - $('#loadSnapshotImport').addClass('disabled'); - } - } - - //console.log(file); - fr.readAsText(file); - }; - - function loadSnapshotPreflightEmpty() { - document.getElementById('loadSnapshotFilename').innerHTML = ''; - document.getElementById('loadSnapshotHostname').innerHTML = ''; - document.getElementById('loadSnapshotURL').innerHTML = ''; - document.getElementById('loadSnapshotCharts').innerHTML = ''; - document.getElementById('loadSnapshotInfo').innerHTML = ''; - document.getElementById('loadSnapshotTimeRange').innerHTML = ''; - document.getElementById('loadSnapshotComments').innerHTML = ''; - loadSnapshotModalLog('success', 'Browse for a snapshot file (or drag it and drop it here), then click <b>Import</b> to render it.'); - $('#loadSnapshotImport').addClass('disabled'); - }; - - var loadSnapshotDragAndDropInitialized = false; - function loadSnapshotDragAndDropSetup() { - if(loadSnapshotDragAndDropInitialized === false) { - loadSnapshotDragAndDropInitialized = true; - $('#loadSnapshotDragAndDrop') - .on('drag dragstart dragend dragover dragenter dragleave drop', function (e) { - e.preventDefault(); - e.stopPropagation(); - }) - .on('drop', function (e) { - if(e.originalEvent.dataTransfer.files.length) { - loadSnapshotPreflightFile(e.originalEvent.dataTransfer.files.item(0)); - } - else { - loadSnapshotPreflightEmpty(); - loadSnapshotModalLog('danger', 'No file selected'); - } - }); - } - }; - - function loadSnapshotPreflight() { - var files = document.getElementById('loadSnapshotSelectFiles').files; - if (files.length <= 0) { - loadSnapshotPreflightEmpty(); - loadSnapshotModalLog('danger', 'No file selected'); - return; - } - - loadSnapshotModalLog('info', 'Loading file...'); - - loadSnapshotPreflightFile(files.item(0)); - } - - // -------------------------------------------------------------------- - // saving snapshots - - var saveSnapshotStop = false; - function saveSnapshotCancel() { - saveSnapshotStop = true; - } - - var saveSnapshotModalInitialized = false; - function saveSnapshotModalSetup() { - if(saveSnapshotModalInitialized === false) { - saveSnapshotModalInitialized = true; - $('#saveSnapshotModal') - .on('hide.bs.modal', saveSnapshotCancel) - .on('show.bs.modal', saveSnapshotModalInit) - .on('shown.bs.modal', function() { - $('#saveSnapshotResolutionSlider').find(".slider-handle:first").attr("tabindex", 1); - document.getElementById('saveSnapshotComments').focus(); - }); - } - }; - - function saveSnapshotModalLog(priority, msg) { - document.getElementById('saveSnapshotStatus').className = "alert alert-" + priority; - document.getElementById('saveSnapshotStatus').innerHTML = msg; - } - - function saveSnapshotModalShowExpectedSize() { - var points = Math.round(saveSnapshotViewDuration / saveSnapshotSelectedSecondsPerPoint); - var priority = 'info'; - var msg = 'A moderate snapshot.'; - - var sizemb = Math.round( - (options.data.charts_count * snapshotOptions.bytes_per_chart - + options.data.dimensions_count * points * snapshotOptions.compressions[saveSnapshotCompression].bytes_per_point_disk) - * 10 / 1024 / 1024) / 10; - - var memmb = Math.round( - (options.data.charts_count * snapshotOptions.bytes_per_chart - + options.data.dimensions_count * points * snapshotOptions.compressions[saveSnapshotCompression].bytes_per_point_memory) - * 10 / 1024 / 1024) / 10; - - if(sizemb < 10) { - priority = 'success'; - msg = 'A nice small snapshot!'; - } - if(sizemb > 50) { - priority = 'warning'; - msg = 'Will stress your browser...'; - } - if(sizemb > 100) { - priority = 'danger'; - msg = 'Hm... good luck...'; - } - - saveSnapshotModalLog(priority, 'The snapshot will have ' + points.toString() + ' points per dimension. Expected size on disk ' + sizemb + ' MB, at browser memory ' + memmb + ' MB.<br/>' + msg); - } - - var saveSnapshotCompression = snapshotOptions.compressionDefault; - function saveSnapshotSetCompression(name) { - saveSnapshotCompression = name; - document.getElementById('saveSnapshotCompressionName').innerHTML = saveSnapshotCompression; - saveSnapshotModalShowExpectedSize(); - } - - var saveSnapshotSlider = null; - var saveSnapshotSelectedSecondsPerPoint = 1; - var saveSnapshotViewDuration = 1; - function saveSnapshotModalInit() { - $('#saveSnapshotModalProgressSection').hide(); - $('#saveSnapshotResolutionRadio').show(); - saveSnapshotModalLog('info', 'Select resolution and click <b>Save</b>'); - $('#saveSnapshotExport').removeClass('disabled'); - - loadBootstrapSlider(function() { - saveSnapshotViewDuration = options.duration; - var start_ms = Math.round(Date.now() - saveSnapshotViewDuration * 1000); - - if(NETDATA.globalPanAndZoom.isActive() === true) { - saveSnapshotViewDuration = Math.round((NETDATA.globalPanAndZoom.force_before_ms - NETDATA.globalPanAndZoom.force_after_ms) / 1000); - start_ms = NETDATA.globalPanAndZoom.force_after_ms; - } - - var start_date = new Date(start_ms); - var yyyymmddhhssmm = start_date.getFullYear() + NETDATA.zeropad(start_date.getMonth() + 1) + NETDATA.zeropad(start_date.getDate()) + '-' + NETDATA.zeropad(start_date.getHours()) + NETDATA.zeropad(start_date.getMinutes()) + NETDATA.zeropad(start_date.getSeconds()); - - document.getElementById('saveSnapshotFilename').value = 'netdata-' + options.hostname.toString() + '-' + yyyymmddhhssmm.toString() + '-' + saveSnapshotViewDuration.toString() + '.snapshot'; - saveSnapshotSetCompression(saveSnapshotCompression); - - var min = options.update_every; - var max = Math.round(saveSnapshotViewDuration / 100); - - if(NETDATA.globalPanAndZoom.isActive() === false) - max = Math.round(saveSnapshotViewDuration / 50); - - var view = Math.round(saveSnapshotViewDuration / Math.round($(document.getElementById('charts_div')).width() / 2)); - - // console.log('view duration: ' + saveSnapshotViewDuration + ', min: ' + min + ', max: ' + max + ', view: ' + view); - - if(max < 10) max = 10; - if(max < min) max = min; - if(view < min) view = min; - if(view > max) view = max; - - if(saveSnapshotSlider !== null) - saveSnapshotSlider.destroy(); - - saveSnapshotSlider = new Slider('#saveSnapshotResolutionSlider', { - ticks: [ min, view, max ], - min: min, - max: max, - step: options.update_every, - value: view, - scale: (max > 100)?'logarithmic':'linear', - tooltip: 'always', - formatter: function(value) { - if(value < 1) - value = 1; - - if(value < options.data.update_every) - value = options.data.update_every; - - saveSnapshotSelectedSecondsPerPoint = value; - saveSnapshotModalShowExpectedSize(); - - var seconds = ' seconds '; - if(value === 1) - seconds = ' second '; - - return value + seconds + 'per point' + ((value === options.data.update_every)?', server default':'').toString(); - } - }); - }); - } - - function saveSnapshot() { - loadPako(function () { - loadLzString(function () { - saveSnapshotStop = false; - $('#saveSnapshotModalProgressSection').show(); - $('#saveSnapshotResolutionRadio').hide(); - $('#saveSnapshotExport').addClass('disabled'); - - var filename = document.getElementById('saveSnapshotFilename').value; - // console.log(filename); - saveSnapshotModalLog('info', 'Generating snapshot as <code>' + filename.toString() + '</code>'); - - var save_options = { - stop_updates_when_focus_is_lost: false, - update_only_visible: false, - sync_selection: false, - eliminate_zero_dimensions: true, - pan_and_zoom_data_padding: false, - show_help: false, - legend_toolbox: false, - resize_charts: false, - pixels_per_point: 1 - }; - var backedup_options = {}; - - var x; - for (x in save_options) { - if (save_options.hasOwnProperty(x)) { - backedup_options[x] = NETDATA.options.current[x]; - NETDATA.options.current[x] = save_options[x]; - } - } - - var el = document.getElementById('saveSnapshotModalProgressBar'); - var eltxt = document.getElementById('saveSnapshotModalProgressBarText'); - - options.data.charts_by_name = null; - - var saveData = { - hostname: options.hostname, - server: NETDATA.serverDefault, - netdata_version: options.data.version, - snapshot_version: 1, - after_ms: Date.now() - options.duration * 1000, - before_ms: Date.now(), - highlight_after_ms: urlOptions.highlight_after, - highlight_before_ms: urlOptions.highlight_before, - duration_ms: options.duration * 1000, - update_every_ms: options.update_every * 1000, - data_points: 0, - url: ((urlOptions.server !== null) ? urlOptions.server : document.location.origin.toString() + document.location.pathname.toString() + document.location.search.toString()).toString(), - comments: document.getElementById('saveSnapshotComments').value.toString(), - hash: urlOptions.hash, - charts: options.data, - info: jsonStringifyFn({ - menu: netdataDashboard.menu, - submenu: netdataDashboard.submenu, - context: netdataDashboard.context - }), - charts_ok: 0, - charts_failed: 0, - compression: saveSnapshotCompression, - data_size: 0, - data: {} - }; - - if(typeof snapshotOptions.compressions[saveData.compression] === 'undefined') { - alert('unknown compression method: ' + saveData.compression); - saveData.compression = 'none'; - } - - var compress = snapshotOptions.compressions[saveData.compression].compress; - var compressed_length = snapshotOptions.compressions[saveData.compression].compressed_length; - - function pack_api1_v1_chart_data(state) { - if (state.library_name === null || state.data === null) - return; - - var data = state.data; - state.data = null; - data.state = null; - var str = JSON.stringify(data); - - if (typeof str === 'string') { - var cstr = compress(str); - saveData.data[state.chartDataUniqueID()] = cstr; - return compressed_length(cstr); - } - else - return 0; - } - - var clearPanAndZoom = false; - if (NETDATA.globalPanAndZoom.isActive() === false) { - NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], saveData.after_ms, saveData.before_ms); - clearPanAndZoom = true; - } - - saveData.after_ms = NETDATA.globalPanAndZoom.force_after_ms; - saveData.before_ms = NETDATA.globalPanAndZoom.force_before_ms; - saveData.duration_ms = saveData.before_ms - saveData.after_ms; - saveData.data_points = Math.round((saveData.before_ms - saveData.after_ms) / (saveSnapshotSelectedSecondsPerPoint * 1000)); - saveSnapshotModalLog('info', 'Generating snapshot with ' + saveData.data_points.toString() + ' data points per dimension...'); - - var charts_count = 0; - var charts_ok = 0; - var charts_failed = 0; - - function saveSnapshotRestore() { - $('#saveSnapshotModal').modal('hide'); - - // restore the options - var x; - for (x in backedup_options) { - if (backedup_options.hasOwnProperty(x)) - NETDATA.options.current[x] = backedup_options[x]; - } - - $(el).css('width', '0%').attr('aria-valuenow', 0); - eltxt.innerText = '0%'; - - if (clearPanAndZoom) - NETDATA.globalPanAndZoom.clearMaster(); - - NETDATA.options.force_data_points = 0; - NETDATA.options.fake_chart_rendering = false; - NETDATA.onscroll_updater_enabled = true; - NETDATA.onresize(); - NETDATA.unpause(); - - $('#saveSnapshotExport').removeClass('disabled'); - } - - NETDATA.globalSelectionSync.stop(); - NETDATA.options.force_data_points = saveData.data_points; - NETDATA.options.fake_chart_rendering = true; - NETDATA.onscroll_updater_enabled = false; - NETDATA.abort_all_refreshes(); - - var size = 0; - var info = ' Resolution: <b>' + saveSnapshotSelectedSecondsPerPoint.toString() + ((saveSnapshotSelectedSecondsPerPoint === 1)?' second ':' seconds ').toString() + 'per point</b>.'; - - function update_chart(idx) { - if (saveSnapshotStop === true) { - saveSnapshotModalLog('info', 'Cancelled!'); - saveSnapshotRestore(); - return; - } - - var state = NETDATA.options.targets[--idx]; - - var pcent = (NETDATA.options.targets.length - idx) * 100 / NETDATA.options.targets.length; - $(el).css('width', pcent + '%').attr('aria-valuenow', pcent); - eltxt.innerText = Math.round(pcent).toString() + '%, ' + state.id; - - setTimeout(function () { - charts_count++; - state.isVisible(true); - state.current.force_after_ms = saveData.after_ms; - state.current.force_before_ms = saveData.before_ms; - - state.updateChart(function (status, reason) { - state.current.force_after_ms = null; - state.current.force_before_ms = null; - - if (status === true) { - charts_ok++; - // state.log('ok'); - size += pack_api1_v1_chart_data(state); - } - else { - charts_failed++; - state.log('failed to be updated: ' + reason); - } - - saveSnapshotModalLog((charts_failed) ? 'danger' : 'info', 'Generated snapshot data size <b>' + (Math.round(size * 100 / 1024 / 1024) / 100).toString() + ' MB</b>. ' + ((charts_failed) ? (charts_failed.toString() + ' charts have failed to be downloaded') : '').toString() + info); - - if (idx > 0) { - update_chart(idx); - } - else { - saveData.charts_ok = charts_ok; - saveData.charts_failed = charts_failed; - saveData.data_size = size; - // console.log(saveData.compression + ': ' + (size / (options.data.dimensions_count * Math.round(saveSnapshotViewDuration / saveSnapshotSelectedSecondsPerPoint))).toString()); - - // save it - // console.log(saveData); - saveObjectToClient(saveData, filename); - - if (charts_failed > 0) - alert(charts_failed.toString() + ' failed to be downloaded'); - - saveSnapshotRestore(); - saveData = null; - } - }) - }, 0); - } - - update_chart(NETDATA.options.targets.length); - }); - }); - } - - // -------------------------------------------------------------------- - // activate netdata on the page - - function dashboardSettingsSetup() { - var update_options_modal = function() { - // console.log('update_options_modal'); - - var sync_option = function(option) { - var self = $('#' + option); - - if(self.prop('checked') !== NETDATA.getOption(option)) { - // console.log('switching ' + option.toString()); - self.bootstrapToggle(NETDATA.getOption(option)?'on':'off'); - } - }; - - var theme_sync_option = function(option) { - var self = $('#' + option); - - self.bootstrapToggle(netdataTheme === 'slate'?'on':'off'); - }; - var units_sync_option = function(option) { - var self = $('#' + option); - - if(self.prop('checked') !== (NETDATA.getOption('units') === 'auto')) { - self.bootstrapToggle(NETDATA.getOption('units') === 'auto' ? 'on' : 'off'); - } - - if(self.prop('checked') === true) { - $('#settingsLocaleTempRow').show(); - $('#settingsLocaleTimeRow').show(); - } - else { - $('#settingsLocaleTempRow').hide(); - $('#settingsLocaleTimeRow').hide(); - } - }; - var temp_sync_option = function(option) { - var self = $('#' + option); - - if(self.prop('checked') !== (NETDATA.getOption('temperature') === 'celsius')) { - self.bootstrapToggle(NETDATA.getOption('temperature') === 'celsius' ? 'on' : 'off'); - } - }; - var timezone_sync_option = function(option) { - var self = $('#' + option); - - document.getElementById('browser_timezone').innerText = NETDATA.options.browser_timezone; - document.getElementById('server_timezone').innerText = NETDATA.options.server_timezone; - document.getElementById('current_timezone').innerText = (NETDATA.options.current.timezone === 'default')?'unset, using browser default':NETDATA.options.current.timezone; - - if(self.prop('checked') === NETDATA.dateTime.using_timezone) { - self.bootstrapToggle(NETDATA.dateTime.using_timezone ? 'off' : 'on'); - } - }; - - 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'); - sync_option('seconds_as_time'); - theme_sync_option('netdata_theme_control'); - units_sync_option('units_conversion'); - temp_sync_option('units_temp'); - timezone_sync_option('local_timezone'); - - 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')); }); - $('#seconds_as_time').change(function() { NETDATA.setOption('seconds_as_time', $(this).prop('checked')); }); - $('#local_timezone').change(function() { - if($(this).prop('checked')) - selected_server_timezone('default', true); - else - selected_server_timezone('default', false); - }); - - - $('#units_conversion').change(function() { - NETDATA.setOption('units', $(this).prop('checked')?'auto':'original'); - }); - $('#units_temp').change(function() { - NETDATA.setOption('temperature', $(this).prop('checked')?'celsius':'fahrenheit'); - }); - - $('#show_help').change(function() { - urlOptions.help = $(this).prop('checked'); - urlOptions.hashUpdate(); - - 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'; - urlOptions.hashUpdate(); - - if(setTheme(urlOptions.theme)) - netdataReload(); - }); - } - - function scrollDashboardTo() { - if(netdataSnapshotData !== null && typeof netdataSnapshotData.hash !== 'undefined') { - //console.log(netdataSnapshotData.hash); - scrollToId(netdataSnapshotData.hash.replace('#','')); - } - else { - // 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); - } - } - } - - var modalHiddenCallback = null; - function scrollToChartAfterHidingModal(chart) { - modalHiddenCallback = function() { - NETDATA.alarms.scrollToChart(chart); - }; - } - - // ---------------------------------------------------------------------------- - - function enableTooltipsAndPopovers() { - $('[data-toggle="tooltip"]').tooltip({ - animated: 'fade', - trigger: 'hover', - html: true, - delay: {show: 500, hide: 0}, - container: 'body' - }); - $('[data-toggle="popover"]').popover(); - } - - // ---------------------------------------------------------------------------- - - var runOnceOnDashboardLastRun = 0; - function runOnceOnDashboardWithjQuery() { - if(runOnceOnDashboardLastRun !== 0) { - scrollDashboardTo(); - - // restore the scrollspy at the proper position - $(document.body).scrollspy('refresh'); - $(document.body).scrollspy('process'); - - return; - } - - runOnceOnDashboardLastRun = Date.now(); - - // ------------------------------------------------------------------------ - // bootstrap modals - - // prevent bootstrap modals from scrolling the page - // maintains the current scroll position - // https://stackoverflow.com/a/34754029/4525767 - - var scrollPos = 0; - var modal_depth = 0; // how many modals are currently open - var modal_shown = false; // set to true, if a modal is shown - var netdata_paused_on_modal = false; // set to true, if the modal paused netdata - var scrollspyOffset = $(window).height() / 3; // will be updated below - the offset of scrollspy to select an item - - $('.modal') - .on('show.bs.modal', function () { - if(modal_depth === 0) { - scrollPos = window.scrollY; - - $('body').css({ - overflow: 'hidden', - position: 'fixed', - top: -scrollPos - }); - - modal_shown = true; - - if (NETDATA.options.pauseCallback === null) { - NETDATA.pause(function () {}); - netdata_paused_on_modal = true; - } - else - netdata_paused_on_modal = false; - } - - modal_depth++; - //console.log(urlOptions.after); - - }) - .on('hide.bs.modal', function () { - - modal_depth--; - - if(modal_depth <= 0) { - modal_depth = 0; - - $('body') - .css({ - overflow: '', - position: '', - top: '' - }); - - // scroll to the position we had open before the modal - $('html, body') - .animate({scrollTop: scrollPos}, 0); - - // unpause netdata, if we paused it - if (netdata_paused_on_modal === true) { - NETDATA.unpause(); - netdata_paused_on_modal = false; - } - - // restore the scrollspy at the proper position - $(document.body).scrollspy('process'); - } - //console.log(urlOptions.after); - }) - .on('hidden.bs.modal', function () { - if(modal_depth === 0) - modal_shown = false; - - if(typeof modalHiddenCallback === 'function') - modalHiddenCallback(); - - modalHiddenCallback = null; - //console.log(urlOptions.after); - }); - - // ------------------------------------------------------------------------ - // sidebar / affix - - $('#sidebar') - .affix({ - offset: { - top: (isdemo())?150:0, - bottom: 0 - } - }) - .on('affixed.bs.affix', function() { - // fix scrolling of very long affix lists - // http://stackoverflow.com/questions/21691585/bootstrap-3-1-0-affix-too-long - - $(this).removeAttr('style'); - }) - .on( 'affix-top.bs.affix', function() { - // fix bootstrap affix click bug - // https://stackoverflow.com/a/37847981/4525767 - - if(modal_shown) return false; - }) - .on('activate.bs.scrollspy', function (e) { - // change the URL based on the current position of the screen - - if(modal_shown === false) { - var el = $(e.target); - var hash = el.find('a').attr('href'); - if (typeof hash === 'string' && hash.substring(0, 1) === '#' && urlOptions.hash.startsWith(hash + '_submenu_') === false) { - urlOptions.hash = hash; - urlOptions.hashUpdate(); - } - } - }); - - Ps.initialize(document.getElementById('sidebar'), { - wheelSpeed: 0.5, - wheelPropagation: true, - swipePropagation: true, - minScrollbarLength: null, - maxScrollbarLength: null, - useBothWheelAxes: false, - suppressScrollX: true, - suppressScrollY: false, - scrollXMarginOffset: 0, - scrollYMarginOffset: 0, - theme: 'default' - }); - - - // ------------------------------------------------------------------------ - // scrollspy - - if(scrollspyOffset > 250) scrollspyOffset = 250; - if(scrollspyOffset < 75) scrollspyOffset = 75; - document.body.setAttribute('data-offset', scrollspyOffset); - - // scroll the dashboard, before activating the scrollspy, so that our - // hash will not be updated before we got the chance to scroll to it - scrollDashboardTo(); - - $(document.body).scrollspy({ - target: '#sidebar', - offset: scrollspyOffset // controls the diff of the <hX> element to the top, to select it - }); - - - // ------------------------------------------------------------------------ - // my-netdata menu - - Ps.initialize(document.getElementById('myNetdataDropdownUL'), { - wheelSpeed: 1, - wheelPropagation: false, - swipePropagation: false, - minScrollbarLength: null, - maxScrollbarLength: null, - useBothWheelAxes: false, - suppressScrollX: true, - suppressScrollY: false, - scrollXMarginOffset: 0, - scrollYMarginOffset: 0, - theme: 'default' - }); - - $('#myNetdataDropdownParent') - .on('show.bs.dropdown', function () { - var hash = urlOptions.genHash(); - $('.registry_link').each(function(idx) { - this.setAttribute('href', this.getAttribute("href").replace(/#.*$/, hash)); - }); - - NETDATA.pause(function() {}); - }) - .on('shown.bs.dropdown', function () { - Ps.update(document.getElementById('myNetdataDropdownUL')); - }) - .on('hidden.bs.dropdown', function () { - NETDATA.unpause(); - }); - - - $('#deleteRegistryModal') - .on('hidden.bs.modal', function() { - deleteRegistryGuid = null; - }); - - - // ------------------------------------------------------------------------ - // update modal - - $('#updateModal') - .on('show.bs.modal', function() { - versionLog('checking, please wait...'); - }) - .on('shown.bs.modal', function() { - notifyForUpdate(true); - }); - - - // ------------------------------------------------------------------------ - // alarms modal - - $('#alarmsModal') - .on('shown.bs.modal', function() { - alarmsUpdateModal(); - }) - .on('hidden.bs.modal', function() { - document.getElementById('alarms_active').innerHTML = - document.getElementById('alarms_all').innerHTML = - document.getElementById('alarms_log').innerHTML = - 'loading...'; - }); - - - // ------------------------------------------------------------------------ - - dashboardSettingsSetup(); - loadSnapshotDragAndDropSetup(); - saveSnapshotModalSetup(); - showPageFooter(); - - - // ------------------------------------------------------------------------ - // 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="fas fa-expand"></i> show more information', - lessText: '<i class="fas fa-compress"></i> show less information', - onLess: function() { NETDATA.onscroll(); }, - onMore: function() { NETDATA.onscroll(); }, - errMsg: null, - force: false - }; - - if (settings) { - $.extend(config, settings); - } - - if ($(this).data('jquery.shorten') && !config.force) { - return false; - } - $(this).data('jquery.shorten', true); - - $(document).off("click", '.morelink'); - - $(document).on({ - click: function() { - - var $this = $(this); - if ($this.hasClass('less')) { - $this.removeClass('less'); - $this.html(config.moreText); - $this.parent().prev().animate({'height':'0'+'%'}, 0, function () { $this.parent().prev().prev().show(); }).hide(0, function() { - config.onLess(); - }); - - } else { - $this.addClass('less'); - $this.html(config.lessText); - $this.parent().prev().animate({'height':'100'+'%'}, 0, function () { $this.parent().prev().prev().hide(); }).show(0, function() { - config.onMore(); - }); - } - return false; - } - }, '.morelink'); - - return this.each(function() { - var $this = $(this); - - var content = $this.html(); - var contentlen = $this.text().length; - if (contentlen > config.showChars + config.minHideChars) { - var c = content.substr(0, config.showChars); - if (c.indexOf('<') >= 0) // If there's HTML don't want to cut it - { - var inTag = false; // I'm in a tag? - var bag = ''; // Put the characters to be shown here - var countChars = 0; // Current bag size - var openTags = []; // Stack for opened tags, so I can close them later - var tagName = null; - - for (var i = 0, r = 0; r <= config.showChars; i++) { - if (content[i] === '<' && !inTag) { - inTag = true; - - // This could be "tag" or "/tag" - tagName = content.substring(i + 1, content.indexOf('>', i)); - - // If its a closing tag - if (tagName[0] === '/') { - - - if (tagName !== ('/' + openTags[0])) { - config.errMsg = 'ERROR en HTML: the top of the stack should be the tag that closes'; - } else { - openTags.shift(); // Pops the last tag from the open tag stack (the tag is closed in the retult HTML!) - } - - } else { - // There are some nasty tags that don't have a close tag like <br/> - if (tagName.toLowerCase() !== 'br') { - openTags.unshift(tagName); // Add to start the name of the tag that opens - } - } - } - if (inTag && content[i] === '>') { - inTag = false; - } - - if (inTag) { bag += content.charAt(i); } // Add tag name chars to the result - else { - r++; - if (countChars <= config.showChars) { - bag += content.charAt(i); // Fix to ie 7 not allowing you to reference string characters using the [] - countChars++; - } else // Now I have the characters needed - { - if (openTags.length > 0) // I have unclosed tags - { - //console.log('They were open tags'); - //console.log(openTags); - for (var j = 0; j < openTags.length; j++) { - //console.log('Cierro tag ' + openTags[j]); - bag += '</' + openTags[j] + '>'; // Close all tags that were opened - - // You could shift the tag from the stack to check if you end with an empty stack, that means you have closed all open tags - } - break; - } - } - } - } - c = $('<div/>').html(bag + '<span class="ellip">' + config.ellipsesText + '</span>').html(); - }else{ - c+=config.ellipsesText; - } - - var html = '<div class="shortcontent">' + c + - '</div><div class="allcontent">' + content + - '</div><span><a href="javascript://nop/" class="morelink">' + config.moreText + '</a></span>'; - - $this.html(html); - $this.find(".allcontent").hide(); // Hide all text - $('.shortcontent p:last', $this).css('margin-bottom', 0); //Remove bottom margin on last paragraph as it's likely shortened - } - }); - }; - } - - 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(); - - // ------------------------------------------------------------------------ - - NETDATA.globalPanAndZoom.callback = null; - NETDATA.globalChartUnderlay.callback = null; - - if(urlOptions.pan_and_zoom === true && NETDATA.options.targets.length > 0) - NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before); - - // callback for us to track PanAndZoom operations - NETDATA.globalPanAndZoom.callback = urlOptions.netdataPanAndZoomCallback; - NETDATA.globalChartUnderlay.callback = urlOptions.netdataHighlightCallback; - - // ------------------------------------------------------------------------ - - // let it run (update the charts) - NETDATA.unpause(); - - runOnceOnDashboardWithjQuery(); - $(".shorten").shorten(); - enableTooltipsAndPopovers(); - - 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() { - (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); - - NETDATA.onresizeCallback = function() { - Ps.update(document.getElementById('sidebar')); - Ps.update(document.getElementById('myNetdataDropdownUL')); - }; - NETDATA.onresizeCallback(); - - if(netdataSnapshotData !== null) { - NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], netdataSnapshotData.after_ms, netdataSnapshotData.before_ms); - } - - // var netdataEnded = performance.now(); - // console.log('start up time: ' + (netdataEnded - netdataStarted).toString() + ' ms'); - } - - function resetDashboardOptions() { - var help = NETDATA.options.current.show_help; - - NETDATA.resetOptions(); - if(setTheme('slate')) - netdataReload(); - - if(help !== NETDATA.options.current.show_help) - netdataReload(); - } - - // callback to add the dashboard info to the - // parallel javascript downloader in netdata - var netdataPrepCallback = function() { - NETDATA.requiredCSS.push({ - url: NETDATA.serverStatic + 'css/bootstrap-toggle-2.2.2.min.css', - isAlreadyLoaded: function() { return false; } - }); - - NETDATA.requiredJs.push({ - url: NETDATA.serverStatic + 'lib/bootstrap-toggle-2.2.2.min.js', - isAlreadyLoaded: function() { return false; } - }); - - NETDATA.requiredJs.push({ - url: NETDATA.serverStatic + 'dashboard_info.js?v20181019-1', - async: false, - isAlreadyLoaded: function() { return false; } - }); - - 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); - } - }; - - var selected_server_timezone = function(timezone, status) { - //console.log('called with timezone: ' + timezone + ", status: " + ((typeof status === 'undefined')?'undefined':status).toString()); - - // clear the error - document.getElementById('timezone_error_message').innerHTML = ''; - - if (typeof status === 'undefined') { - // the user selected a timezone from the menu - - NETDATA.setOption('user_set_server_timezone', timezone); - - if (NETDATA.dateTime.init(timezone) === false) { - NETDATA.dateTime.init(); - - if(!$('#local_timezone').prop('checked')) - $('#local_timezone').bootstrapToggle('on'); - - document.getElementById('timezone_error_message').innerHTML = 'Ooops! That timezone was not accepted by your browser. Please open a github issue to help us fix it.'; - NETDATA.setOption('user_set_server_timezone', NETDATA.options.server_timezone); - } - else { - if($('#local_timezone').prop('checked')) - $('#local_timezone').bootstrapToggle('off'); - } - } - else if (status === true) { - // the user wants the browser default timezone to be activated - - NETDATA.dateTime.init(); - } - else { - // the user wants the server default timezone to be activated - //console.log('found ' + NETDATA.options.current.user_set_server_timezone); - - if (NETDATA.options.current.user_set_server_timezone === 'default') - NETDATA.options.current.user_set_server_timezone = NETDATA.options.server_timezone; - - timezone = NETDATA.options.current.user_set_server_timezone; - - if (NETDATA.dateTime.init(timezone) === false) { - NETDATA.dateTime.init(); - - if(!$('#local_timezone').prop('checked')) - $('#local_timezone').bootstrapToggle('on'); - - document.getElementById('timezone_error_message').innerHTML = 'Sorry. The timezone "' + timezone.toString() + '" is not accepted by your browser. Please select one from the list.'; - NETDATA.setOption('user_set_server_timezone', NETDATA.options.server_timezone); - } - } - - document.getElementById('current_timezone').innerText = (NETDATA.options.current.timezone === 'default')?'unset, using browser default':NETDATA.options.current.timezone; - return false; - }; - - // our entry point - // var netdataStarted = performance.now(); - - var netdataCallback = initializeDynamicDashboard; - </script> + <script src="main.js?v=2"></script> </head> <body data-spy="scroll" data-target="#sidebar" data-offset="100"> @@ -4543,8 +59,17 @@ netdata<br/><div style="font-size: 3vh;">Real-time performance monitoring, done right!</div> </div> <script type="text/javascript"> - // change the loadOverlay colors ASAP to match the theme - document.getElementById('loadOverlay').style = (urlOptions.theme === 'slate')?"background-color:#272b30; color: #373b40;":"background-color:#fff; color: #ddd;"; + // Change the loadOverlay colors ASAP to match the theme. + let theme; + const hash = document.location.hash; + if (hash.includes('theme=slate')) { + theme = 'slate'; + } else if (hash.includes('theme=white')) { + theme = 'white'; + } else { + theme = localStorage.getItem('netdataTheme') || 'slate'; + } + document.getElementById('loadOverlay').style = theme == 'slate' ? "background-color: #272b30; color: #373b40;" : "background-color: #fff; color: #ddd;"; </script> <nav class="navbar navbar-default navbar-fixed-top" role="banner"> <div class="container"> @@ -4552,20 +77,8 @@ <ul class="nav navbar-nav"> <li class="dropdown" id="myNetdataDropdownParent" title="your other netdata servers" data-toggle="tooltip" data-placement="right"> <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"> - <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li> - </ul> - </div> - <div class="col-sm-3 hidden-xs" style="width: 15%; padding-left: 0;"> - <ul id="mynetdata_actions1" class="multi-column-dropdown"> - <li style="color: #999;"> </li> - </ul> - </div> - </div> - </ul> + <div id="my-netdata-dropdown-content" class="dropdown-menu scrollable-menu inpagemenu"> + </div> </li> </ul> </nav> @@ -4646,56 +159,15 @@ <div class="row"> <div class="col-md-10" role="main"> <div class="p"> - <big><a href="https://github.com/netdata/netdata/wiki" target="_blank">netdata</a></big><br/> + <big><a href="https://github.com/netdata/netdata/wiki" target="_blank">Netdata</a></big> + <br /><br /> + <i class="fas fa-copyright"></i> Copyright 2018, <a href="mailto:info@netdata.cloud">Netdata, Inc</a>.<br/> <i class="fas fa-copyright"></i> Copyright 2016-2018, <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"> - <small> - <a href="https://github.com/netdata/netdata/wiki" target="_blank">netdata</a> uses the following third party tools on this dashboard: - - <i class="fas fa-circle"></i> The excellent <a href="http://dygraphs.com/" target="_blank">Dygraphs.com</a> web chart library, - <i class="fas fa-copyright"></i> Copyright 2009, Dan Vanderkam, <a href="http://dygraphs.com/legal.html" target="_blank">MIT License</a> - - <i class="fas fa-circle"></i> <a href="https://rendro.github.io/easy-pie-chart/" target="_blank">Easy Pie Chart</a> web chart library, - <i class="fas fa-copyright"></i> Copyright 2013, Robert Fleischmann, <a href="https://github.com/rendro/easy-pie-chart/blob/master/LICENSE" target="_blank">MIT License</a> - - <i class="fas fa-circle"></i> <a href="http://bernii.github.io/gauge.js/" target="_blank">Gauge.js</a> web chart library, - <i class="fas fa-copyright"></i> Copyright, Bernard Kobos, <a href="http://bernii.github.io/gauge.js/" target="_blank">MIT License</a> - - <i class="fas fa-circle"></i> <a href="https://github.com/benkeen/d3pie" target="_blank">d3pie</a> web chart library, - <i class="fas fa-copyright"></i> Copyright 2014-2015 Benjamin Keen, <a href="https://github.com/benkeen/d3pie/blob/master/LICENSE" target="_blank">MIT License</a> - - <i class="fas fa-circle"></i> <a href="http://d3js.org/" target="_blank">D3</a> web graphics library, - <i class="fas fa-copyright"></i> Copyright 2015 Mike Bostock, <a href="http://opensource.org/licenses/BSD-3-Clause" target="_blank">BSD License</a> - - <i class="fas fa-circle"></i> <a href="https://jquery.org/" target="_blank">jQuery</a>, - <i class="fas fa-copyright"></i> Copyright 2015, jQuery Foundation, <a href="https://jquery.org/license/" target="_blank">MIT License</a> - - <i class="fas fa-circle"></i> <a href="http://getbootstrap.com/getting-started/" target="_blank">Bootstrap</a>, - <i class="fas fa-copyright"></i> Copyright 2015, Twitter, <a href="http://getbootstrap.com/getting-started/#license-faqs" target="_blank">MIT License</a> - - <i class="fas fa-circle"></i> <a href="http://www.bootstraptoggle.com/" target="_blank">Bootstrap Toggle</a>, - <i class="fas fa-copyright"></i> Copyright 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="fas fa-circle"></i> <a href="http://seiyria.com/bootstrap-slider/" target="_blank">Bootstrap-slider</a>, - <i class="fas fa-copyright"></i> Copyright 2017 Kyle Kemp, Rohit Kalkur, and contributors, <a href="https://github.com/seiyria/bootstrap-slider/blob/master/LICENSE.md" target="_blank">MIT License</a> - - <i class="fas fa-circle"></i> <a href="https://github.com/noraesae/perfect-scrollbar" target="_blank">perfect-scrollbar</a>, - <i class="fas 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="fas fa-circle"></i> <a href="https://fortawesome.github.io/Font-Awesome/" target="_blank">FontAwesome</a>, - <i class="fas fa-copyright"></i> Created by Dave Gandy, Font: <a href="http://scripts.sil.org/OFL" target="_blank">SIL OFL 1.1 License</a>, CSS: <a href="http://opensource.org/licenses/mit-license.html" target="_blank">MIT License</a> - - <i class="fas fa-circle"></i> <a href="http://www.iconsdb.com/soylent-red-icons/seo-performance-icon.html" target="_blank">IconsDB.com Icons</a>, Icons provided as CC0 1.0 Universal (CC0 1.0) Public Domain Dedication. - - <i class="fas fa-circle"></i> <a href="http://bootstrap-table.wenzhixin.net.cn/" target="_blank">bootstrap-table</a>, - <i class="fas fa-copyright"></i> Copyright 2012-2016 Zhixin Wen, <a href="https://github.com/wenzhixin/bootstrap-table/blob/master/LICENSE" target="_blank">MIT License</a> - - <i class="fas fa-circle"></i> <a href="https://github.com/hhurz/tableExport.jquery.plugin" target="_blank">tableExport.jquery.plugin</a>, - <i class="fas fa-copyright"></i> Copyright 2015,2016 hhurz, <a href="http://rawgit.com/hhurz/tableExport.jquery.plugin/master/tableExport.js" target="_blank">MIT License</a> - - </small> + Released under <a href="http://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">GPL v3 or later</a>. + Netdata uses <a href="https://github.com/netdata/netdata/blob/master/REDISTRIBUTED.md" target="_blank">third party tools</a>. + <br /><br /> </div> </div> </div> @@ -4946,7 +418,7 @@ <div class="p"> <b><a href="https://github.com/netdata/netdata/wiki" target="_blank">netdata</a></b> is free, open-source software. If you decide to use it, - <strong><a href="https://github.com/netdata/netdata/wiki/a-github-star-is-important" target="_blank">it is important to give netdata a star at GitHub</a></strong>. + <strong><a href="https://github.com/netdata/netdata/tree/master/doc/a-github-star-is-important.md" target="_blank">it is important to give netdata a star at GitHub</a></strong>. </div> <div class="p"> Enjoy real-time performance monitoring! @@ -5786,6 +1258,6 @@ </div> </div> <div id="hiddenDownloadLinks" style="display: none;" hidden></div> - <script type="text/javascript" src="dashboard.js?v20181013-2"></script> + <script type="text/javascript" src="dashboard.js?v20181114-1"></script> </body> </html> |