@cryptotaxi247 / netdata-1 / commits / 62d39bf29

dashboard show tooltip on charts, with the context and the resolution of the chart; fixes #2829; fixes #2708

Costa Tsaousis (ktsaou) committed Oct 3, 2017 at 01:53 UTC 62d39bf294d25c847f2504165f176f2a97a6dd16
2 files changed +105 -76
web/dashboard.js
+94 -1
@@ -2869,6 +2869,18 @@ var NETDATA = window.NETDATA || {};
2869 return this.colors;
2870 };
2871
2872 + this.legendResolutionTooltip = function () {
2873 + if(!this.chart) return '';
2874 +
2875 + var collected = this.chart.update_every;
2876 + var viewed = (this.data)?this.data.view_update_every:collected;
2877 +
2878 + if(collected === viewed)
2879 + return "resolution " + NETDATA.seconds4human(collected);
2880 +
2881 + return "resolution " + NETDATA.seconds4human(viewed) + ", collected every " + NETDATA.seconds4human(collected);
2882 + };
2883 +
2884 this.legendUpdateDOM = function() {
2885 var needed = false, dim, keys, len, i;
2886
@@ -3189,6 +3201,11 @@ var NETDATA = window.NETDATA || {};
3201 that.resizeHandler(e);
3202 }, false);
3203
3204 + if(this.chart) {
3205 + this.element_legend_childs.title_date.title = this.chart.context.toString();
3206 + this.element_legend_childs.title_time.title = this.legendResolutionTooltip();
3207 + }
3208 +
3209 this.element_legend_childs.title_date.className += " netdata-legend-title-date";
3210 this.element_legend.appendChild(this.element_legend_childs.title_date);
3211 this.tmp.__last_shown_legend_date = undefined;
@@ -3450,14 +3467,22 @@ var NETDATA = window.NETDATA || {};
3467 this.updates_since_last_creation++;
3468
3469 var started = Date.now();
3470 + var view_update_every = data.view_update_every * 1000;
3471 +
3472 +
3473 + if(this.data_update_every !== view_update_every) {
3474 + if(this.element_legend_childs.title_time)
3475 + this.element_legend_childs.title_time.title = this.legendResolutionTooltip();
3476 + }
3477
3478 // if the result is JSON, find the latest update-every
3455 - this.data_update_every = data.view_update_every * 1000;
3479 + this.data_update_every = view_update_every;
3480 this.data_after = data.after * 1000;
3481 this.data_before = data.before * 1000;
3482 this.netdata_first = data.first_entry * 1000;
3483 this.netdata_last = data.last_entry * 1000;
3484 this.data_points = data.points;
3485 +
3486 data.state = this;
3487
3488 if(NETDATA.options.current.pan_and_zoom_data_padding === true && this.requested_padding !== null) {
@@ -4036,6 +4061,74 @@ var NETDATA = window.NETDATA || {};
4061 NETDATA.options.pause = false;
4062 };
4063
4064 + NETDATA.seconds4human = function (seconds, options) {
4065 + var default_options = {
4066 + now: 'now',
4067 + space: ' ',
4068 + negative_suffix: 'ago',
4069 + day: 'day',
4070 + days: 'days',
4071 + hour: 'hour',
4072 + hours: 'hours',
4073 + minute: 'min',
4074 + minutes: 'mins',
4075 + second: 'sec',
4076 + seconds: 'secs',
4077 + and: 'and'
4078 + };
4079 +
4080 + if(typeof options !== 'object')
4081 + options = default_options;
4082 + else {
4083 + var x;
4084 + for(x in default_options) {
4085 + if(typeof options[x] !== 'string')
4086 + options[x] = default_options[x];
4087 + }
4088 + }
4089 +
4090 + if(typeof seconds === 'string')
4091 + seconds = parseInt(seconds);
4092 +
4093 + if(seconds === 0)
4094 + return options.now;
4095 +
4096 + var suffix = '';
4097 + if(seconds < 0) {
4098 + seconds = -seconds;
4099 + if(options.negative_suffix !== '') suffix = options.space + options.negative_suffix;
4100 + }
4101 +
4102 + var days = Math.floor(seconds / 86400);
4103 + seconds -= (days * 86400);
4104 +
4105 + var hours = Math.floor(seconds / 3600);
4106 + seconds -= (hours * 3600);
4107 +
4108 + var minutes = Math.floor(seconds / 60);
4109 + seconds -= (minutes * 60);
4110 +
4111 + var strings = [];
4112 +
4113 + if(days > 1) strings.push(days.toString() + options.space + options.days);
4114 + else if(days === 1) strings.push(days.toString() + options.space + options.day);
4115 +
4116 + if(hours > 1) strings.push(hours.toString() + options.space + options.hours);
4117 + else if(hours === 1) strings.push(hours.toString() + options.space + options.hour);
4118 +
4119 + if(minutes > 1) strings.push(minutes.toString() + options.space + options.minutes);
4120 + else if(minutes === 1) strings.push(minutes.toString() + options.space + options.minute);
4121 +
4122 + if(seconds > 1) strings.push(Math.floor(seconds).toString() + options.space + options.seconds);
4123 + else if(seconds === 1) strings.push(Math.floor(seconds).toString() + options.space + options.second);
4124 +
4125 + if(strings.length === 1)
4126 + return strings.pop() + suffix;
4127 +
4128 + var last = strings.pop();
4129 + return strings.join(", ") + " " + options.and + " " + last + suffix;
4130 + };
4131 +
4132 // ----------------------------------------------------------------------------------------------------------------
4133
4134 // this is purely sequential charts refresher
web/index.html
+11 -75
@@ -1540,7 +1540,7 @@
1540
1541 sidebar += '<li class="" style="padding-top:15px;"><a href="https://github.com/firehol/netdata/wiki/Add-more-charts-to-netdata" target="_blank"><i class="fa fa-plus" aria-hidden="true"></i> add more charts</a></li>';
1542 sidebar += '<li class=""><a href="https://github.com/firehol/netdata/wiki/Add-more-alarms-to-netdata" target="_blank"><i class="fa fa-plus" aria-hidden="true"></i> add more alarms</a></li>';
1543 - sidebar += '<li class="" style="margin:20px;color:#666;"><small>netdata on <b>' + data.hostname.toString() + '</b>, collects every ' + ((data.update_every === 1)?'second':data.update_every.toString() + ' seconds') + ' <b>' + data.dimensions_count.toLocaleString() + '</b> metrics, presented as <b>' + data.charts_count.toLocaleString() + '</b> charts and monitored by <b>' + data.alarms_count.toLocaleString() + '</b> alarms, using ' + Math.round(data.rrd_memory_bytes / 1024 / 1024).toLocaleString() + ' MB of memory for ' + seconds4human(data.update_every * data.history) + ' of real-time history.<br/>&nbsp;<br/><b>netdata</b><br/>v' + data.version.toString() +'</small></li>';
1543 + 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: '&nbsp;' }) + ' of real-time history.<br/>&nbsp;<br/><b>netdata</b><br/>v' + data.version.toString() +'</small></li>';
1544 sidebar += '</ul>';
1545 div.innerHTML = html;
1546 document.getElementById('sidebar').innerHTML = sidebar;
@@ -1711,7 +1711,7 @@
1711
1712 return '<code>' + alarm.lookup_method + '</code> '
1713 + dimensions + ', of chart <code>' + alarm.chart + '</code>'
1714 - + ', starting <code>' + seconds4human(alarm.lookup_after + alarm.lookup_before) + '</code> and up to <code>' + seconds4human(alarm.lookup_before) + '</code>'
1714 + + ', starting <code>' + NETDATA.seconds4human(alarm.lookup_after + alarm.lookup_before, { space: '&nbsp;' }) + '</code> and up to <code>' + NETDATA.seconds4human(alarm.lookup_before, { space: '&nbsp;' }) + '</code>'
1715 + ((alarm.lookup_options)?(', with options <code>' + alarm.lookup_options.replace(' ', ',&nbsp;') + '</code>'):'')
1716 + '.';
1717 }
@@ -1747,25 +1747,25 @@
1747 var delay = '';
1748 if((alarm.delay_up_duration > 0 || alarm.delay_down_duration > 0) && alarm.delay_multiplier !== 0 && alarm.delay_max_duration > 0) {
1749 if(alarm.delay_up_duration === alarm.delay_down_duration) {
1750 - delay += '<small><br/>hysteresis ' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' });
1750 + delay += '<small><br/>hysteresis ' + NETDATA.seconds4human(alarm.delay_up_duration, { space: '&nbsp;', negative_suffix: '' });
1751 }
1752 else {
1753 delay = '<small><br/>hysteresis ';
1754 if(alarm.delay_up_duration > 0) {
1755 - delay += 'on&nbsp;escalation&nbsp;<code>' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' }) + '</code>, ';
1755 + delay += 'on&nbsp;escalation&nbsp;<code>' + NETDATA.seconds4human(alarm.delay_up_duration, { space: '&nbsp;', negative_suffix: '' }) + '</code>, ';
1756 }
1757 if(alarm.delay_down_duration > 0) {
1758 - delay += 'on&nbsp;recovery&nbsp;<code>' + seconds4human(alarm.delay_down_duration, { negative_suffix: '' }) + '</code>, ';
1758 + delay += 'on&nbsp;recovery&nbsp;<code>' + NETDATA.seconds4human(alarm.delay_down_duration, { space: '&nbsp;', negative_suffix: '' }) + '</code>, ';
1759 }
1760 }
1761 if(alarm.delay_multiplier !== 1.0) {
1762 delay += 'multiplied&nbsp;by&nbsp;<code>' + alarm.delay_multiplier.toString() + '</code>';
1763 - delay += ',&nbsp;up&nbsp;to&nbsp;<code>' + seconds4human(alarm.delay_max_duration, { negative_suffix: '' }) + '</code>';
1763 + delay += ',&nbsp;up&nbsp;to&nbsp;<code>' + NETDATA.seconds4human(alarm.delay_max_duration, { space: '&nbsp;', negative_suffix: '' }) + '</code>';
1764 }
1765 delay += '</small>';
1766 }
1767
1768 - html += '<tr><td width="10%" style="text-align:right">check&nbsp;every</td><td>' + seconds4human(alarm.update_every, { negative_suffix: '' }) + '</td></tr>'
1768 + html += '<tr><td width="10%" style="text-align:right">check&nbsp;every</td><td>' + NETDATA.seconds4human(alarm.update_every, { space: '&nbsp;', negative_suffix: '' }) + '</td></tr>'
1769 + ((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>'):'')
1770 + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>'
1771 + '</table></td></tr>';
@@ -2103,7 +2103,7 @@
2103 formatter: function(value, row, index) {
2104 void(row);
2105 void(index);
2106 - return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
2106 + return NETDATA.seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
2107 },
2108 align: 'center',
2109 valign: 'middle',
@@ -2117,7 +2117,7 @@
2117 formatter: function(value, row, index) {
2118 void(row);
2119 void(index);
2120 - return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
2120 + return NETDATA.seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
2121 },
2122 align: 'center',
2123 valign: 'middle',
@@ -2234,7 +2234,7 @@
2234 void(row);
2235 void(index);
2236
2237 - return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
2237 + return NETDATA.seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
2238 },
2239 align: 'center',
2240 valign: 'middle',
@@ -2276,70 +2276,6 @@
2276 });
2277 }
2278
2279 - function seconds4human(seconds, options) {
2280 - var default_options = {
2281 - now: 'now',
2282 - space: '&nbsp;',
2283 - negative_suffix: 'ago',
2284 - hour: 'hour',
2285 - hours: 'hours',
2286 - minute: 'minute',
2287 - minutes: 'minutes',
2288 - second: 'second',
2289 - seconds: 'seconds',
2290 - and: 'and'
2291 - };
2292 -
2293 - if(typeof options !== 'object')
2294 - options = default_options;
2295 - else {
2296 - var x;
2297 - for(x in default_options) {
2298 - if(typeof options[x] !== 'string')
2299 - options[x] = default_options[x];
2300 - }
2301 - }
2302 -
2303 - if(typeof seconds === 'string')
2304 - seconds = parseInt(seconds);
2305 -
2306 - if(seconds === 0)
2307 - return options.now;
2308 -
2309 - var suffix = '';
2310 - if(seconds < 0) {
2311 - seconds = -seconds;
2312 - if(options.negative_suffix !== '') suffix = options.space + options.negative_suffix;
2313 - }
2314 -
2315 - var hours = Math.floor(seconds / 3600);
2316 - seconds -= (hours * 3600);
2317 -
2318 - var minutes = Math.floor(seconds / 60);
2319 - seconds -= (minutes * 60);
2320 -
2321 - var txt = '';
2322 -
2323 - if(hours > 1) txt += hours.toString() + options.space + options.hours;
2324 - else if(hours === 1) txt += hours.toString() + options.space + options.hour;
2325 -
2326 - if(hours > 0 && minutes > 0 && seconds === 0)
2327 - txt += options.space + options.and + options.space;
2328 - else if(hours > 0 && minutes > 0 && seconds > 0)
2329 - txt += ',' + options.space;
2330 -
2331 - if(minutes > 1) txt += minutes.toString() + options.space + options.minutes;
2332 - else if(minutes === 1) txt += minutes.toString() + options.space + options.minute;
2333 -
2334 - if((minutes > 0 || minutes > 0) && seconds > 0)
2335 - txt += options.space + options.and + options.space;
2336 -
2337 - if(seconds > 1) txt += Math.floor(seconds).toString() + options.space + options.seconds;
2338 - else if(seconds === 1) txt += Math.floor(seconds).toString() + options.space + options.second;
2339 -
2340 - return txt + suffix;
2341 - }
2342 -
2279 function alarmsCallback(data) {
2280 var count = 0;
2281 for(x in data.alarms) {
@@ -3597,4 +3533,4 @@
3533 </div>
3534 </body>
3535 </html>
3600 -<script type="text/javascript" src="dashboard.js?v20170815-14"></script>
3536 +<script type="text/javascript" src="dashboard.js?v20171003-20"></script>