Center the chart on timeframe when an alarm is raised (#6391)
##### Summary When an alarm happens, we were sending notification for our users, but the notifications were missing an important information that allows to centralize the Chart to demonstrate to our users. ##### Component Name UI ##### Additional Information Closes #5810
thiagoftsm committed
Sep 17, 2019 at 08:44 UTC
7485fed6ba94ccd6c6382944bd5bf917db0fae49
4 files changed
+52
-5
health/notifications/alarm-notify.sh.in
+1
-1
@@ -1783,7 +1783,7 @@ url_family="${REPLY}"
1783
urlencode "${name}" >/dev/null
1784
url_name="${REPLY}"
1785
1786
-redirect_params="host=${url_host}&chart=${url_chart}&family=${url_family}&alarm=${url_name}&alarm_unique_id=${unique_id}&alarm_id=${alarm_id}&alarm_event_id=${event_id}"
1786
+redirect_params="host=${url_host}&chart=${url_chart}&family=${url_family}&alarm=${url_name}&alarm_unique_id=${unique_id}&alarm_id=${alarm_id}&alarm_event_id=${event_id}&alarm_when=${when}"
1787
GOTOCLOUD=0
1788
1789
if [ "${NETDATA_REGISTRY_URL}" == "https://registry.my-netdata.io" ]; then
web/gui/goto-host-from-alarm.html
+2
@@ -69,6 +69,7 @@ var urlOptions = {
69
alarm_unique_id: 0,
70
alarm_id: 0,
71
alarm_event_id: 0,
72
+ alarm_when: 0,
73
hasProperty: function(property) {
74
return typeof this[property] !== 'undefined';
75
}
@@ -101,6 +102,7 @@ function netdataURL(url) {
102
+ ';alarm_unique_id=' + urlOptions.alarm_unique_id.toString()
103
+ ';alarm_id=' + urlOptions.alarm_id.toString()
104
+ ';alarm_event_id=' + urlOptions.alarm_event_id.toString()
105
+ + ';alarm_when=' + urlOptions.alarm_when.toString()
106
;
107
}
108
web/gui/main.css
+4
@@ -383,6 +383,10 @@ body.modal-open {
383
384
/* -------------------------------------------------------------------------- */
385
386
+#alarms_log_table tbody tr {
387
+ cursor: pointer;
388
+}
389
+
390
#my-netdata-dropdown-content {
391
width: 500px;
392
}
web/gui/main.js
+45
-4
@@ -71,6 +71,7 @@ var urlOptions = {
71
alarm_unique_id: 0,
72
alarm_id: 0,
73
alarm_event_id: 0,
74
+ alarm_when: 0,
75
76
hasProperty: function (property) {
77
// console.log('checking property ' + property + ' of type ' + typeof(this[property]));
@@ -139,7 +140,7 @@ var urlOptions = {
140
}
141
}
142
142
- var numeric = ['after', 'before', 'highlight_after', 'highlight_before'];
143
+ var numeric = ['after', 'before', 'highlight_after', 'highlight_before', 'alarm_when'];
144
len = numeric.length;
145
while (len--) {
146
if (typeof urlOptions[numeric[len]] === 'string') {
@@ -153,6 +154,22 @@ var urlOptions = {
154
}
155
}
156
157
+ if (urlOptions.alarm_when) {
158
+ // if alarm_when exists, create after/before params
159
+ // -/+ 2 minutes from the alarm, and reload the page
160
+ const alarmTime = new Date(urlOptions.alarm_when * 1000).valueOf();
161
+ const timeMarginMs = 120000; // 2 mins
162
+
163
+ const after = alarmTime - timeMarginMs;
164
+ const before = alarmTime + timeMarginMs;
165
+ const newHash = document.location.hash.replace(
166
+ /;alarm_when=[0-9]*/i,
167
+ ";after=" + after + ";before=" + before,
168
+ );
169
+ history.replaceState(null, '', newHash);
170
+ location.reload();
171
+ }
172
+
173
if (urlOptions.server !== null && urlOptions.server !== '') {
174
netdataServerStatic = document.location.origin.toString() + document.location.pathname.toString();
175
netdataServer = urlOptions.server;
@@ -2094,7 +2111,7 @@ function alarmsUpdateModal() {
2111
var badge_url = NETDATA.alarms.server + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto';
2112
2113
var action_buttons = '<br/> <br/>role: <b>' + alarm.recipient + '</b><br/> <br/>'
2097
- + '<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>'
2114
+ + '<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 + '\', ' + alarm.last_status_change * 1000 + ', \'' + alarm.status + '\'); $(\'#alarmsModal\').modal(\'hide\'); return false;"><i class="fab fa-periscope"></i></div>'
2115
+ '<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>'
2116
+ '<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>';
2117
@@ -2335,6 +2352,18 @@ function alarmsUpdateModal() {
2352
exportOptions: {
2353
fileName: 'netdata_alarm_log'
2354
},
2355
+ onClickRow: function (row, $element,field) {
2356
+ void (field);
2357
+ void ($element);
2358
+ let main_url;
2359
+ let common_url = "&host=" + encodeURIComponent(row['hostname']) + "&chart=" + encodeURIComponent(row['chart']) + "&family=" + encodeURIComponent(row['family']) + "&alarm=" + encodeURIComponent(row['name']) + "&alarm_unique_id=" + row['unique_id'] + "&alarm_id=" + row['alarm_id'] + "&alarm_event_id=" + row['alarm_event_id'] + "&alarm_when=" + row['when'];
2360
+ if (NETDATA.registry.isUsingGlobalRegistry() && NETDATA.registry.machine_guid != null) {
2361
+ main_url = "https://netdata.cloud/alarms/redirect?agentID=" + NETDATA.registry.machine_guid + common_url;
2362
+ } else {
2363
+ main_url = NETDATA.registry.server + "/goto-host-from-alarm.html?" + common_url ;
2364
+ }
2365
+ window.open(main_url,"_blank");
2366
+ },
2367
rowStyle: function (row, index) {
2368
void (index);
2369
@@ -3965,9 +3994,21 @@ function scrollDashboardTo() {
3994
3995
var modalHiddenCallback = null;
3996
3968
-function scrollToChartAfterHidingModal(chart) {
3997
+function scrollToChartAfterHidingModal(chart, alarmDate, alarmStatus) {
3998
modalHiddenCallback = function () {
3970
- NETDATA.alarms.scrollToChart(chart);
3999
+ NETDATA.alarms.scrollToChart(chart, alarmDate);
4000
+
4001
+ if (['WARNING', 'CRITICAL'].includes(alarmStatus)) {
4002
+ const currentChartState = NETDATA.options.targets.find(
4003
+ (chartState) => chartState.id === chart,
4004
+ )
4005
+ const twoMinutes = 2 * 60 * 1000
4006
+ NETDATA.globalPanAndZoom.setMaster(
4007
+ currentChartState,
4008
+ alarmDate - twoMinutes,
4009
+ alarmDate + twoMinutes,
4010
+ )
4011
+ }
4012
};
4013
}
4014