diff options
Diffstat (limited to 'web/dashboard.js')
-rw-r--r-- | web/dashboard.js | 530 |
1 files changed, 459 insertions, 71 deletions
diff --git a/web/dashboard.js b/web/dashboard.js index 67fb00b8..4dd86391 100644 --- a/web/dashboard.js +++ b/web/dashboard.js @@ -12,11 +12,17 @@ // var netdataNoBootstrap = true; // do not load bootstrap // var netdataDontStart = true; // do not start the thread to process the charts // var netdataErrorCallback = null; // Callback function that will be invoked upon error -// var netdataNoRegistry = true; // Don't update the registry for this access +// var netdataRegistry = true; // Update the registry (default disabled) // var netdataRegistryCallback = null; // Callback function that will be invoked with one param, // the URLs from the registry -// var netdataShowHelp = true; // enable/disable help -// var netdataShowAlarms = true; // enable/disable help +// var netdataShowHelp = false; // enable/disable help (default enabled) +// var netdataShowAlarms = true; // enable/disable alarms checks and notifications (default disabled) +// +// var netdataRegistryAfterMs = 1500 // the time to consult to registry on startup +// +// var netdataCallback = null; // a function to call when netdata is ready +// // netdata will be running while this is called (call NETDATA.pause to stop it) +// var netdataPrepCallback = null; // a callback to be called before netdata does anything else // // You can also set the default netdata server, using the following. // When this variable is not set, we assume the page is hosted on your @@ -50,6 +56,15 @@ // global namespace var NETDATA = window.NETDATA || {}; + NETDATA.name2id = function(s) { + return s + .replace(/ /g, '_') + .replace(/\(/g, '_') + .replace(/\)/g, '_') + .replace(/\./g, '_') + .replace(/\//g, '_'); + }; + // ---------------------------------------------------------------------------------------------------------------- // Detect the netdata server @@ -93,25 +108,25 @@ // default URLs for all the external files we need // make them RELATIVE so that the whole thing can also be // installed under a web server - NETDATA.jQuery = NETDATA.serverDefault + 'lib/jquery-1.12.0.min.js'; - NETDATA.peity_js = NETDATA.serverDefault + 'lib/jquery.peity.min.js'; - NETDATA.sparkline_js = NETDATA.serverDefault + 'lib/jquery.sparkline.min.js'; - NETDATA.easypiechart_js = NETDATA.serverDefault + 'lib/jquery.easypiechart.min.js'; - NETDATA.gauge_js = NETDATA.serverDefault + 'lib/gauge.min.js'; - NETDATA.dygraph_js = NETDATA.serverDefault + 'lib/dygraph-combined.js'; - NETDATA.dygraph_smooth_js = NETDATA.serverDefault + 'lib/dygraph-smooth-plotter.js'; - NETDATA.raphael_js = NETDATA.serverDefault + 'lib/raphael-min.js'; - NETDATA.morris_js = NETDATA.serverDefault + 'lib/morris.min.js'; - NETDATA.d3_js = NETDATA.serverDefault + 'lib/d3.min.js'; - NETDATA.c3_js = NETDATA.serverDefault + 'lib/c3.min.js'; - NETDATA.c3_css = NETDATA.serverDefault + 'css/c3.min.css'; - NETDATA.morris_css = NETDATA.serverDefault + 'css/morris.css'; + NETDATA.jQuery = NETDATA.serverDefault + 'lib/jquery-2.2.4.min.js'; + NETDATA.peity_js = NETDATA.serverDefault + 'lib/jquery.peity-3.2.0.min.js'; + NETDATA.sparkline_js = NETDATA.serverDefault + 'lib/jquery.sparkline-2.1.2.min.js'; + NETDATA.easypiechart_js = NETDATA.serverDefault + 'lib/jquery.easypiechart-97b5824.min.js'; + NETDATA.gauge_js = NETDATA.serverDefault + 'lib/gauge-d5260c3.min.js'; + NETDATA.dygraph_js = NETDATA.serverDefault + 'lib/dygraph-combined-dd74404.js'; + NETDATA.dygraph_smooth_js = NETDATA.serverDefault + 'lib/dygraph-smooth-plotter-dd74404.js'; + NETDATA.raphael_js = NETDATA.serverDefault + 'lib/raphael-2.2.4-min.js'; + NETDATA.c3_js = NETDATA.serverDefault + 'lib/c3-0.4.11.min.js'; + NETDATA.c3_css = NETDATA.serverDefault + 'css/c3-0.4.11.min.css'; + NETDATA.d3_js = NETDATA.serverDefault + 'lib/d3-3.5.17.min.js'; + NETDATA.morris_js = NETDATA.serverDefault + 'lib/morris-0.5.1.min.js'; + NETDATA.morris_css = NETDATA.serverDefault + 'css/morris-0.5.1.css'; NETDATA.google_js = 'https://www.google.com/jsapi'; NETDATA.themes = { white: { - bootstrap_css: NETDATA.serverDefault + 'css/bootstrap.min.css', - dashboard_css: NETDATA.serverDefault + 'dashboard.css', + bootstrap_css: NETDATA.serverDefault + 'css/bootstrap-3.3.7.min.css', + dashboard_css: NETDATA.serverDefault + 'dashboard.css?v20161002-1', background: '#FFFFFF', foreground: '#000000', grid: '#DDDDDD', @@ -127,12 +142,12 @@ gauge_gradient: false }, slate: { - bootstrap_css: NETDATA.serverDefault + 'css/bootstrap.slate.min.css', - dashboard_css: NETDATA.serverDefault + 'dashboard.slate.css', + bootstrap_css: NETDATA.serverDefault + 'css/bootstrap.slate.min.css?v20161002-1', + dashboard_css: NETDATA.serverDefault + 'dashboard.slate.css?v20161002-1', background: '#272b30', foreground: '#C8C8C8', - grid: '#373b40', - axis: '#373b40', + grid: '#35393e', + axis: '#35393e', /* colors: [ '#55bb33', '#ff2222', '#0099C6', '#faa11b', '#adbce0', '#DDDD00', '#4178ba', '#f58122', '#a5cc39', '#f58667', '#f5ef89', '#cf93c0', '#a5d18a', '#b8539d', '#3954a3', '#c8a9cf', '#c7de8a', '#fad20a', @@ -155,12 +170,6 @@ else NETDATA.themes.current = NETDATA.themes.white; - if(typeof netdataShowHelp === 'undefined') - netdataShowHelp = true; - - if(typeof netdataShowAlarms === 'undefined') - netdataShowAlarms = true; - NETDATA.colors = NETDATA.themes.current.colors; // these are the colors Google Charts are using @@ -175,6 +184,25 @@ // (blue) (red) (orange) (green) (pink) (brown) (purple) (yellow) (gray) //NETDATA.colors = [ '#5DA5DA', '#F15854', '#FAA43A', '#60BD68', '#F17CB0', '#B2912F', '#B276B2', '#DECF3F', '#4D4D4D' ]; + if(typeof netdataShowHelp === 'undefined') + netdataShowHelp = true; + + if(typeof netdataShowAlarms === 'undefined') + netdataShowAlarms = false; + + if(typeof netdataRegistryAfterMs !== 'number' || netdataRegistryAfterMs < 0) + netdataRegistryAfterMs = 1500; + + if(typeof netdataRegistry === 'undefined') { + // backward compatibility + if(typeof netdataNoRegistry !== 'undefined' && netdataNoRegistry === false) + netdataRegistry = true; + else + netdataRegistry = false; + } + if(netdataRegistry === false && typeof netdataRegistryCallback === 'function') + netdataRegistry = true; + // ---------------------------------------------------------------------------------------------------------------- // the defaults for all charts @@ -300,7 +328,9 @@ pan_and_zoom_factor_multiplier_shift: 3.0, pan_and_zoom_factor_multiplier_alt: 4.0, - abort_ajax_on_scroll: false, + abort_ajax_on_scroll: false, // kill pending ajax page scroll + async_on_scroll: false, // sync/async onscroll handler + onscroll_worker_duration_threshold: 30, // time in ms, to consider slow the onscroll handler setOptionCallback: function() { ; } }, @@ -475,21 +505,29 @@ NETDATA.onscroll(); }; - NETDATA.onscroll = function() { - // console.log('onscroll'); - - NETDATA.options.last_page_scroll = new Date().getTime(); - NETDATA.options.auto_refresher_stop_until = 0; + NETDATA.onscroll_updater_count = 0; + NETDATA.onscroll_updater_running = false; + NETDATA.onscroll_updater_last_run = 0; + NETDATA.onscroll_updater_watchdog = null; + NETDATA.onscroll_updater_max_duration = 0; + NETDATA.onscroll_updater_above_threshold_count = 0; + NETDATA.onscroll_updater = function() { + NETDATA.onscroll_updater_running = true; + NETDATA.onscroll_updater_count++; + var start = new Date().getTime(); - if(NETDATA.options.targets === null) return; + var targets = NETDATA.options.targets; + var len = targets.length; // when the user scrolls he sees that we have // hidden all the not-visible charts // using this little function we try to switch // the charts back to visible quickly - var targets = NETDATA.options.targets; - var len = targets.length; + + if(NETDATA.options.abort_ajax_on_scroll === true) { + // we have to cancel pending requests too + while (len--) { if (targets[len]._updating === true) { if (typeof targets[len].xhr !== 'undefined') { @@ -502,9 +540,69 @@ } } else { + // just find which chart is visible + while (len--) targets[len].isVisible(); } + + var end = new Date().getTime(); + // console.log('scroll No ' + NETDATA.onscroll_updater_count + ' calculation took ' + (end - start).toString() + ' ms'); + + if(NETDATA.options.current.async_on_scroll === false) { + var dt = end - start; + if(dt > NETDATA.onscroll_updater_max_duration) { + // console.log('max onscroll event handler duration increased to ' + dt); + NETDATA.onscroll_updater_max_duration = dt; + } + + if(dt > NETDATA.options.current.onscroll_worker_duration_threshold) { + // console.log('slow: ' + dt); + NETDATA.onscroll_updater_above_threshold_count++; + + if(NETDATA.onscroll_updater_above_threshold_count > 2 && NETDATA.onscroll_updater_above_threshold_count * 100 / NETDATA.onscroll_updater_count > 2) { + NETDATA.setOption('async_on_scroll', true); + console.log('NETDATA: your browser is slow - enabling asynchronous onscroll event handler.'); + } + } + } + + NETDATA.onscroll_updater_last_run = start; + NETDATA.onscroll_updater_running = false; + }; + + NETDATA.onscroll = function() { + // console.log('onscroll'); + + NETDATA.options.last_page_scroll = new Date().getTime(); + NETDATA.options.auto_refresher_stop_until = 0; + + if(NETDATA.options.targets === null) return; + + if(NETDATA.options.current.async_on_scroll === true) { + // async + if(NETDATA.onscroll_updater_running === false) { + NETDATA.onscroll_updater_running = true; + setTimeout(NETDATA.onscroll_updater, 0); + } + else { + if(NETDATA.onscroll_updater_watchdog !== null) + clearTimeout(NETDATA.onscroll_updater_watchdog); + + NETDATA.onscroll_updater_watchdog = setTimeout(function() { + if(NETDATA.onscroll_updater_running === false && NETDATA.options.last_page_scroll > NETDATA.onscroll_updater_last_run) { + // console.log('watchdog'); + NETDATA.onscroll_updater(); + } + + NETDATA.onscroll_updater_watchdog = null; + }, 200); + } + } + else { + // sync + NETDATA.onscroll_updater(); + } }; window.onresize = NETDATA.onresize; @@ -530,7 +628,9 @@ 413: { message: "Netdata registry server send invalid response to SWITCH ", alert: false }, 414: { message: "Netdata registry SWITCH failed", alert: false }, 415: { message: "Netdata alarms download failed", alert: false }, - 416: { message: "Netdata alarms log download failed", alert: false } + 416: { message: "Netdata alarms log download failed", alert: false }, + 417: { message: "Netdata registry server send invalid response to SEARCH ", alert: false }, + 418: { message: "Netdata registry SEARCH failed", alert: false } }; NETDATA.errorLast = { code: 0, @@ -3448,11 +3548,13 @@ NETDATA.parseDom(NETDATA.chartRefresher); // Alarms initialization - if(netdataShowAlarms === true) - setTimeout(NETDATA.alarms.init, 1000); + setTimeout(NETDATA.alarms.init, 1000); // Registry initialization - setTimeout(NETDATA.registry.init, 1500); + setTimeout(NETDATA.registry.init, netdataRegistryAfterMs); + + if(typeof netdataCallback === 'function') + netdataCallback(); }; // ---------------------------------------------------------------------------------------------------------------- @@ -3857,7 +3959,7 @@ showLabelsOnHighlight: self.data('dygraph-showlabelsonhighlight') || true, hideOverlayOnMouseOut: self.data('dygraph-hideoverlayonmouseout') || true, - includeZero: self.data('dygraph-includezero') || false, + includeZero: self.data('dygraph-includezero') || ((chart_type === 'stacked')? true : false), xRangePad: self.data('dygraph-xrangepad') || 0, yRangePad: self.data('dygraph-yrangepad') || 1, @@ -3901,10 +4003,8 @@ axisLineWidth: self.data('dygraph-axislinewidth') || 0.3, drawGrid: self.data('dygraph-drawgrid') || true, - drawXGrid: self.data('dygraph-drawxgrid') || undefined, - drawYGrid: self.data('dygraph-drawygrid') || undefined, gridLinePattern: self.data('dygraph-gridlinepattern') || null, - gridLineWidth: self.data('dygraph-gridlinewidth') || 0.3, + gridLineWidth: self.data('dygraph-gridlinewidth') || 0.4, gridLineColor: self.data('dygraph-gridlinecolor') || NETDATA.themes.current.grid, maxNumberWidth: self.data('dygraph-maxnumberwidth') || 8, @@ -4273,7 +4373,6 @@ state.dygraph_options.drawGrid = false; state.dygraph_options.drawAxis = false; state.dygraph_options.title = undefined; - state.dygraph_options.units = undefined; state.dygraph_options.ylabel = undefined; state.dygraph_options.yLabelWidth = 0; state.dygraph_options.labelsDivWidth = 120; @@ -4961,6 +5060,7 @@ else if(typeof status === 'number') speed = status; + // console.log('gauge speed ' + speed); state.gauge_instance.animationSpeed = speed; state.___gaugeOld__.speed = speed; }; @@ -4994,6 +5094,7 @@ if(pcent > 100) pcent = 100; state.gauge_instance.set(pcent); + // console.log('gauge set ' + pcent + ', value ' + value + ', min ' + min + ', max ' + max); state.___gaugeOld__.value = value; state.___gaugeOld__.min = min; @@ -5476,7 +5577,8 @@ NETDATA.requiredJs = [ { - url: NETDATA.serverDefault + 'lib/bootstrap.min.js', + url: NETDATA.serverDefault + 'lib/bootstrap-3.3.7.min.js', + async: false, isAlreadyLoaded: function() { // check if bootstrap is loaded if(typeof $().emulateTransitionEnd == 'function') @@ -5490,11 +5592,7 @@ } }, { - url: NETDATA.serverDefault + 'lib/jquery.nanoscroller.min.js', - isAlreadyLoaded: function() { return false; } - }, - { - url: NETDATA.serverDefault + 'lib/bootstrap-toggle.min.js', + url: NETDATA.serverDefault + 'lib/jquery.nanoscroller-0.8.7.min.js', isAlreadyLoaded: function() { return false; } } ]; @@ -5510,27 +5608,25 @@ } }, { - url: NETDATA.serverDefault + 'css/font-awesome.min.css', + url: NETDATA.serverDefault + 'css/font-awesome.min.css?v4.6.3', isAlreadyLoaded: function() { return false; } }, { url: NETDATA.themes.current.dashboard_css, isAlreadyLoaded: function() { return false; } - }, - { - url: NETDATA.serverDefault + 'css/bootstrap-toggle.min.css', - isAlreadyLoaded: function() { return false; } } ]; + NETDATA.loadedRequiredJs = 0; NETDATA.loadRequiredJs = function(index, callback) { - if(index >= NETDATA.requiredJs.length) { + if(index >= NETDATA.requiredJs.length) { if(typeof callback === 'function') callback(); return; } if(NETDATA.requiredJs[index].isAlreadyLoaded()) { + NETDATA.loadedRequiredJs++; NETDATA.loadRequiredJs(++index, callback); return; } @@ -5538,21 +5634,32 @@ if(NETDATA.options.debug.main_loop === true) console.log('loading ' + NETDATA.requiredJs[index].url); + var async = true; + if(typeof NETDATA.requiredJs[index].async !== 'undefined' && NETDATA.requiredJs[index].async === false) + async = false; + $.ajax({ url: NETDATA.requiredJs[index].url, cache: true, dataType: "script", xhrFields: { withCredentials: true } // required for the cookie }) - .success(function() { + .done(function() { if(NETDATA.options.debug.main_loop === true) console.log('loaded ' + NETDATA.requiredJs[index].url); - - NETDATA.loadRequiredJs(++index, callback); }) .fail(function() { alert('Cannot load required JS library: ' + NETDATA.requiredJs[index].url); }) + .always(function() { + NETDATA.loadedRequiredJs++; + + if(async === false) + NETDATA.loadRequiredJs(++index, callback); + }) + + if(async === true) + NETDATA.loadRequiredJs(++index, callback); }; NETDATA.loadRequiredCSS = function(index) { @@ -5576,22 +5683,248 @@ // Registry of netdata hosts NETDATA.alarms = { - current: null, - callback: null, + onclick: null, // the callback to handle the click - it will be called with the alarm log entry + chart_div_offset: 100, // give that space above the chart when scrolling to it + chart_div_id_prefix: 'chart_', // the chart DIV IDs have this prefix (they should be NETDATA.name2id(chart.id)) + chart_div_animation_duration: 0,// the duration of the animation while scrolling to a chart + + ms_penalty: 0, // the time penalty of the next alarm + ms_between_notifications: 500, // firefox moves the alarms off-screen (above, outside the top of the screen) + // if alarms are shown faster than: one per 500ms + + notifications: false, // when true, the browser supports notifications (may not be granted though) + last_notification_id: 0, // the id of the last alarm_log we have raised an alarm for + first_notification_id: 0, // the id of the first alarm_log entry for this session + // this is used to prevent CLEAR notifications for past events + // notifications_shown: new Array(), + + server: null, // the server to connect to for fetching alarms + current: null, // the list of raised alarms - updated in the background + callback: null, // a callback function to call every time the list of raised alarms is refreshed + + notify: function(entry) { + // console.log('alarm ' + entry.unique_id); + + if(entry.updated === true) { + // console.log('alarm ' + entry.unique_id + ' has been updated by another alarm'); + return; + } + + var value = entry.value; + if(NETDATA.alarms.current !== null) { + var t = NETDATA.alarms.current.alarms[entry.chart + '.' + entry.name]; + if(typeof t !== 'undefined' && entry.status == t.status) + value = t.value; + } + + var name = entry.name.replace(/_/g, ' '); + var status = entry.status.toLowerCase(); + var title = name + ' = ' + ((value === null)?'NaN':Math.floor(value)).toString() + ' ' + entry.units; + var tag = entry.alarm_id; + var icon = 'images/seo-performance-128.png'; + var interaction = false; + var data = entry; + var show = true; + + // console.log('alarm ' + entry.unique_id + ' ' + entry.chart + '.' + entry.name + ' is ' + entry.status); + + switch(entry.status) { + case 'REMOVED': + show = false; + break; + + case 'UNDEFINED': + return; + + case 'UNINITIALIZED': + return; + + case 'CLEAR': + if(entry.unique_id < NETDATA.alarms.first_notification_id) { + // console.log('alarm ' + entry.unique_id + ' is not current'); + return; + } + if(entry.old_status === 'UNINITIALIZED' || entry.old_status === 'UNDEFINED') { + // console.log('alarm' + entry.unique_id + ' switch to CLEAR from ' + entry.old_status); + return; + } + title = name + ' back to normal'; + icon = 'images/check-mark-2-128-green.png' + interaction = false; + break; + + case 'WARNING': + if(entry.old_status === 'CRITICAL') + status = 'demoted to ' + entry.status.toLowerCase(); + + icon = 'images/alert-128-orange.png'; + interaction = false; + break; + + case 'CRITICAL': + if(entry.old_status === 'WARNING') + status = 'escalated to ' + entry.status.toLowerCase(); + + icon = 'images/alert-128-red.png' + interaction = true; + break; + + default: + console.log('invalid alarm status ' + entry.status); + return; + } + + /* + // cleanup old notifications with the same alarm_id as this one + // FIXME: it does not seem to work on any web browser! + var len = NETDATA.alarms.notifications_shown.length; + while(len--) { + var n = NETDATA.alarms.notifications_shown[len]; + if(n.data.alarm_id === entry.alarm_id) { + console.log('removing old alarm ' + n.data.unique_id); + + // close the notification + n.close.bind(n); + + // remove it from the array + NETDATA.alarms.notifications_shown.splice(len, 1); + len = NETDATA.alarms.notifications_shown.length; + } + } + */ + + if(show === true) { + + setTimeout(function() { + // show this notification + // console.log('new notification: ' + title); + var n = new Notification(title, { + body: entry.hostname + ' - ' + entry.chart + ' (' + entry.family + ') - ' + status + ': ' + entry.info, + tag: tag, + requireInteraction: interaction, + icon: NETDATA.serverDefault + icon, + data: data + }); + + n.onclick = function(event) { + event.preventDefault(); + NETDATA.alarms.onclick(event.target.data); + }; + + // console.log(n); + // NETDATA.alarms.notifications_shown.push(n); + // console.log(entry); + }, NETDATA.alarms.ms_penalty); + + NETDATA.alarms.ms_penalty += NETDATA.alarms.ms_between_notifications; + } + }, + + scrollToChart: function(chart_id) { + if(typeof chart_id === 'string') { + var offset = $('#' + NETDATA.alarms.chart_div_id_prefix + NETDATA.name2id(chart_id)).offset(); + if(typeof offset !== 'undefined') { + $('html, body').animate({ scrollTop: offset.top - NETDATA.alarms.chart_div_offset }, NETDATA.alarms.chart_div_animation_duration); + return true; + } + } + return false; + }, + + scrollToAlarm: function(alarm) { + if(typeof alarm === 'object') { + var ret = NETDATA.alarms.scrollToChart(alarm.chart); + + if(ret === true && NETDATA.options.page_is_visible === false) + window.focus(); + // alert('netdata dashboard will now scroll to chart: ' + alarm.chart + '\n\nThis alarm opened to bring the browser window in front of the screen. Click on the dashboard to prevent it from appearing again.'); + } + + }, + + notifyAll: function() { + // console.log('FETCHING ALARM LOG'); + NETDATA.alarms.get_log(NETDATA.alarms.last_notification_id, function(data) { + // console.log('ALARM LOG FETCHED'); + + if(data === null || typeof data !== 'object') { + console.log('invalid alarms log response'); + return; + } + + if(data.length === 0) { + console.log('received empty alarm log'); + return; + } + + // console.log('received alarm log of ' + data.length + ' entries, from ' + data[data.length - 1].unique_id.toString() + ' to ' + data[0].unique_id.toString()); + + data.sort(function(a, b) { + if(a.unique_id > b.unique_id) return -1; + if(a.unique_id < b.unique_id) return 1; + return 0; + }); + + NETDATA.alarms.ms_penalty = 0; + + var len = data.length; + while(len--) { + if(data[len].unique_id > NETDATA.alarms.last_notification_id) { + NETDATA.alarms.notify(data[len]); + } + //else + // console.log('ignoring alarm (older) with id ' + data[len].unique_id.toString()); + } + + NETDATA.alarms.last_notification_id = data[0].unique_id; + NETDATA.localStorageSet('last_notification_id', NETDATA.alarms.last_notification_id, null); + // console.log('last notification id = ' + NETDATA.alarms.last_notification_id); + }) + }, + + check_notifications: function() { + // returns true if we should fire 1+ notifications + + if(NETDATA.alarms.notifications !== true) { + // console.log('notifications not available'); + return false; + } + + if(Notification.permission !== 'granted') { + // console.log('notifications not granted'); + return false; + } + + if(typeof NETDATA.alarms.current !== 'undefined' && typeof NETDATA.alarms.current.alarms === 'object') { + // console.log('can do alarms: old id = ' + NETDATA.alarms.last_notification_id + ' new id = ' + NETDATA.alarms.current.latest_alarm_log_unique_id); + + if(NETDATA.alarms.current.latest_alarm_log_unique_id > NETDATA.alarms.last_notification_id) { + // console.log('new alarms detected'); + return true; + } + //else console.log('no new alarms'); + } + // else console.log('cannot process alarms'); + + return false; + }, get: function(what, callback) { $.ajax({ - url: NETDATA.serverDefault + '/api/v1/alarms?' + what.toString(), + url: NETDATA.alarms.server + '/api/v1/alarms?' + what.toString(), async: true, cache: false, xhrFields: { withCredentials: true } // required for the cookie }) .done(function(data) { + if(NETDATA.alarms.first_notification_id === 0 && typeof data.latest_alarm_log_unique_id === 'number') + NETDATA.alarms.first_notification_id = data.latest_alarm_log_unique_id; + if(typeof callback === 'function') callback(data); }) .fail(function() { - NETDATA.error(415, host); + NETDATA.error(415, NETDATA.alarms.server); if(typeof callback === 'function') callback(null); @@ -5603,18 +5936,26 @@ if(data !== null) { NETDATA.alarms.current = data; + if(NETDATA.alarms.check_notifications() === true) { + NETDATA.alarms.notifyAll(); + } + if (typeof NETDATA.alarms.callback === 'function') { NETDATA.alarms.callback(data); } + + // Health monitoring is disabled on this netdata + if(data.status === false) return; } setTimeout(NETDATA.alarms.update_forever, 10000); }); }, - get_log: function(callback) { + get_log: function(last_id, callback) { + // console.log('fetching all log after ' + last_id.toString()); $.ajax({ - url: NETDATA.serverDefault + '/api/v1/alarm_log', + url: NETDATA.alarms.server + '/api/v1/alarm_log?after=' + last_id.toString(), async: true, cache: false, xhrFields: { withCredentials: true } // required for the cookie @@ -5624,7 +5965,7 @@ callback(data); }) .fail(function() { - NETDATA.error(416, host); + NETDATA.error(416, NETDATA.alarms.server); if(typeof callback === 'function') callback(null); @@ -5632,7 +5973,27 @@ }, init: function() { - NETDATA.alarms.update_forever(); + var host = NETDATA.serverDefault; + while(host.slice(-1) === '/') + host = host.substring(0, host.length - 1); + NETDATA.alarms.server = host; + + NETDATA.alarms.last_notification_id = NETDATA.localStorageGet('last_notification_id', NETDATA.alarms.last_notification_id, null); + + if(NETDATA.alarms.onclick === null) + NETDATA.alarms.onclick = NETDATA.alarms.scrollToAlarm; + + if(netdataShowAlarms === true) { + NETDATA.alarms.update_forever(); + + if('Notification' in window) { + // console.log('notifications available'); + NETDATA.alarms.notifications = true; + + if(Notification.permission === 'default') + Notification.requestPermission(); + } + } } }; @@ -5696,8 +6057,7 @@ }, init: function() { - if(typeof netdataNoRegistry !== 'undefined' && netdataNoRegistry) - return; + if(netdataRegistry !== true) return; NETDATA.registry.hello(NETDATA.serverDefault, function(data) { if(data) { @@ -5816,6 +6176,31 @@ }); }, + search: function(machine_guid, callback) { + // SEARCH for the URLs of a machine: + $.ajax({ + url: NETDATA.registry.server + '/api/v1/registry?action=search&machine=' + NETDATA.registry.machine_guid + '&name=' + encodeURIComponent(NETDATA.registry.hostname) + '&url=' + encodeURIComponent(NETDATA.serverDefault) + '&for=' + machine_guid, + async: true, + cache: false, + xhrFields: { withCredentials: true } // required for the cookie + }) + .done(function(data) { + if(typeof data.status !== 'string' || data.status !== 'ok') { + NETDATA.error(417, NETDATA.registry.server + ' responded with: ' + JSON.stringify(data)); + data = null; + } + + if(typeof callback === 'function') + callback(data); + }) + .fail(function() { + NETDATA.error(418, NETDATA.registry.server); + + if(typeof callback === 'function') + callback(null); + }); + }, + switch: function(new_person_guid, callback) { // impersonate $.ajax({ @@ -5845,6 +6230,9 @@ // ---------------------------------------------------------------------------------------------------------------- // Boot it! + if(typeof netdataPrepCallback === 'function') + netdataPrepCallback(); + NETDATA.errorReset(); NETDATA.loadRequiredCSS(0); |