From: Costa Tsaousis (ktsaou) Date: Thu, 26 Jan 2017 11:15:36 +0000 (+0200) Subject: pretty value formatting on all alarm notifications X-Git-Tag: ab-debian_0.20170201.01-0ab1~22^2~12 X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netdata.git;a=commitdiff_plain;h=dcd95ef8fd7e665f99b567042afa1d1e500f14e5 pretty value formatting on all alarm notifications --- diff --git a/src/health.c b/src/health.c index 193312ee..8b0f761e 100755 --- a/src/health.c +++ b/src/health.c @@ -290,6 +290,10 @@ static inline ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char ae->new_value = str2l(pointers[25]); ae->old_value = str2l(pointers[26]); + static char value_string[100 + 1]; + ae->old_value_string = strdupz(format_value_and_unit(value_string, 100, ae->old_value, ae->units, -1)); + ae->new_value_string = strdupz(format_value_and_unit(value_string, 100, ae->new_value, ae->units, -1)); + // add it to host if not already there if(unlikely(*pointers[0] == 'A')) { ae->next = host->health_log.alarms; @@ -391,6 +395,11 @@ static inline void health_alarm_log(RRDHOST *host, ae->when = when; ae->old_value = old_value; ae->new_value = new_value; + + static char value_string[100 + 1]; + ae->old_value_string = strdupz(format_value_and_unit(value_string, 100, ae->old_value, ae->units, -1)); + ae->new_value_string = strdupz(format_value_and_unit(value_string, 100, ae->new_value, ae->units, -1)); + ae->old_status = old_status; ae->new_status = new_status; ae->duration = duration; @@ -2331,7 +2340,9 @@ static inline void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae, R "\t\t\"delay\": %d,\n" "\t\t\"delay_up_to_timestamp\": %lu,\n" "\t\t\"updated_by_id\": %u,\n" - "\t\t\"updates_id\": %u,\n", + "\t\t\"updates_id\": %u,\n" + "\t\t\"value_string\": \"%s\",\n" + "\t\t\"old_value_string\": \"%s\",\n", host->hostname, ae->unique_id, ae->alarm_id, @@ -2357,7 +2368,9 @@ static inline void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae, R ae->delay, (unsigned long)ae->delay_up_to_timestamp, ae->updated_by_id, - ae->updates_id + ae->updates_id, + ae->new_value_string, + ae->old_value_string ); buffer_strcat(wb, "\t\t\"value\":"); @@ -2643,7 +2656,7 @@ static inline void health_alarm_execute(RRDHOST *host, ALARM_ENTRY *ae) { const char *recipient = ae->recipient; if(!recipient) recipient = health.health_default_recipient; - snprintfz(command_to_run, ALARM_EXEC_COMMAND_LENGTH, "exec %s '%s' '%s' '%u' '%u' '%u' '%lu' '%s' '%s' '%s' '%s' '%s' '%0.0Lf' '%0.0Lf' '%s' '%u' '%u' '%s' '%s'", + snprintfz(command_to_run, ALARM_EXEC_COMMAND_LENGTH, "exec %s '%s' '%s' '%u' '%u' '%u' '%lu' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%u' '%u' '%s' '%s'", exec, recipient, host->hostname, @@ -2656,8 +2669,8 @@ static inline void health_alarm_execute(RRDHOST *host, ALARM_ENTRY *ae) { ae->family?ae->family:"NOFAMILY", rrdcalc_status2string(ae->new_status), rrdcalc_status2string(ae->old_status), - ae->new_value, - ae->old_value, + ae->new_value_string, + ae->old_value_string, ae->source?ae->source:"UNKNOWN", (uint32_t)ae->duration, (uint32_t)ae->non_clear_duration, @@ -2754,6 +2767,8 @@ static inline void health_alarm_log_process(RRDHOST *host) { freez(ae->source); freez(ae->units); freez(ae->info); + freez(ae->old_value_string); + freez(ae->new_value_string); freez(ae); ae = t; diff --git a/src/health.h b/src/health.h index 79831d4f..f009e4ab 100644 --- a/src/health.h +++ b/src/health.h @@ -308,6 +308,10 @@ typedef struct alarm_entry { calculated_number old_value; calculated_number new_value; + + char *old_value_string; + char *new_value_string; + int old_status; int new_status; diff --git a/src/web_buffer_svg.c b/src/web_buffer_svg.c index 31b193a5..bdc1608e 100644 --- a/src/web_buffer_svg.c +++ b/src/web_buffer_svg.c @@ -368,7 +368,64 @@ cleanup: return len - i; } -static inline int fix_value_and_units(char *value_string, size_t value_string_len, calculated_number value, const char **units_ptr, int value_is_null) { +static inline char *format_value_with_precision_and_unit(char *value_string, size_t value_string_len, calculated_number value, const char *units, int precision) { + if(unlikely(isnan(value) || isinf(value))) + value = 0.0; + + char *separator = ""; + if(unlikely(isalnum(*units))) + separator = " "; + + if(precision < 0) { + int len, lstop = 0, trim_zeros = 1; + + calculated_number abs = value; + if(isless(value, 0)) { + lstop = 1; + abs = -value; + } + + if(isgreaterequal(abs, 1000)) { + len = snprintfz(value_string, value_string_len, "%0.0Lf", (long double) value); + trim_zeros = 0; + } + else if(isgreaterequal(abs, 100)) len = snprintfz(value_string, value_string_len, "%0.1Lf", (long double) value); + else if(isgreaterequal(abs, 1)) len = snprintfz(value_string, value_string_len, "%0.2Lf", (long double) value); + else if(isgreaterequal(abs, 0.1)) len = snprintfz(value_string, value_string_len, "%0.3Lf", (long double) value); + else len = snprintfz(value_string, value_string_len, "%0.4Lf", (long double) value); + + if(unlikely(trim_zeros)) { + int l; + // remove trailing zeros from the decimal part + for(l = len - 1; l > lstop; l--) { + if(likely(value_string[l] == '0')) { + value_string[l] = '\0'; + len--; + } + + else if(unlikely(value_string[l] == '.')) { + value_string[l] = '\0'; + len--; + break; + } + + else + break; + } + } + + if(unlikely(len <= 0)) len = 1; + snprintfz(&value_string[len], value_string_len - len, "%s%s", separator, units); + } + else { + if(precision > 50) precision = 50; + snprintfz(value_string, value_string_len, "%0.*Lf%s%s", precision, (long double) value, separator, units); + } + + return value_string; +} + +inline char *format_value_and_unit(char *value_string, size_t value_string_len, calculated_number value, const char *units, int precision) { static uint32_t hash_seconds = 0, hash_seconds_ago = 0, @@ -404,7 +461,6 @@ static inline int fix_value_and_units(char *value_string, size_t value_string_le hash_pcent = simple_hash("pcent"); } - const char *units = (units_ptr)?*units_ptr:NULL; if(unlikely(!units)) units = ""; uint32_t hash_units = simple_hash(units); @@ -412,13 +468,11 @@ static inline int fix_value_and_units(char *value_string, size_t value_string_le if(unlikely((hash_units == hash_seconds && !strcmp(units, "seconds")) || (hash_units == hash_seconds_ago && !strcmp(units, "seconds ago")))) { if(value == 0.0) { snprintfz(value_string, value_string_len, "%s", "now"); - units = ""; - goto finish; + return value_string; } else if(isnan(value) || isinf(value)) { snprintfz(value_string, value_string_len, "%s", "never"); - units = ""; - goto finish; + return value_string; } const char *suffix = (hash_units == hash_seconds_ago)?" ago":""; @@ -438,19 +492,17 @@ static inline int fix_value_and_units(char *value_string, size_t value_string_le else snprintfz(value_string, value_string_len, "%02zu:%02zu:%02zu%s", h, m, s, suffix); - units = ""; + return value_string; } else if(unlikely((hash_units == hash_minutes && !strcmp(units, "minutes")) || (hash_units == hash_minutes_ago && !strcmp(units, "minutes ago")))) { if(value == 0.0) { snprintfz(value_string, value_string_len, "%s", "now"); - units = ""; - goto finish; + return value_string; } else if(isnan(value) || isinf(value)) { snprintfz(value_string, value_string_len, "%s", "never"); - units = ""; - goto finish; + return value_string; } const char *suffix = (hash_units == hash_minutes_ago)?" ago":""; @@ -467,19 +519,17 @@ static inline int fix_value_and_units(char *value_string, size_t value_string_le else snprintfz(value_string, value_string_len, "%zuh %zum%s", h, m, suffix); - units = ""; + return value_string; } else if(unlikely((hash_units == hash_hours && !strcmp(units, "hours")) || (hash_units == hash_hours_ago && !strcmp(units, "hours ago")))) { if(value == 0.0) { snprintfz(value_string, value_string_len, "%s", "now"); - units = ""; - goto finish; + return value_string; } else if(isnan(value) || isinf(value)) { snprintfz(value_string, value_string_len, "%s", "never"); - units = ""; - goto finish; + return value_string; } const char *suffix = (hash_units == hash_hours_ago)?" ago":""; @@ -493,27 +543,27 @@ static inline int fix_value_and_units(char *value_string, size_t value_string_le else snprintfz(value_string, value_string_len, "%zuh%s", h, suffix); - units = ""; + return value_string; } else if(unlikely(hash_units == hash_onoff && !strcmp(units, "on/off"))) { snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"on":"off"); - units = ""; + return value_string; } else if(unlikely(hash_units == hash_updown && !strcmp(units, "up/down"))) { snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"up":"down"); - units = ""; + return value_string; } else if(unlikely(hash_units == hash_okerror && !strcmp(units, "ok/error"))) { snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"ok":"error"); - units = ""; + return value_string; } else if(unlikely(hash_units == hash_okfailed && !strcmp(units, "ok/failed"))) { snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"ok":"failed"); - units = ""; + return value_string; } else if(unlikely(hash_units == hash_empty && !strcmp(units, "empty"))) @@ -531,16 +581,13 @@ static inline int fix_value_and_units(char *value_string, size_t value_string_le else if(unlikely(hash_units == hash_pcent && !strcmp(units, "pcent"))) units = "%"; - else if(unlikely(value_is_null)) { + + if(unlikely(isnan(value) || isinf(value))) { strcpy(value_string, "-"); - units = ""; + return value_string; } - else - return 0; -finish: - if(units_ptr) *units_ptr = units; - return 1; + return format_value_with_precision_and_unit(value_string, value_string_len, value, units, precision); } static inline const char *color_map(const char *color) { @@ -560,9 +607,12 @@ static inline const char *color_map(const char *color) { return color; } -static inline void calc_colorz(const char *color, char *final, size_t len, calculated_number value, int value_is_null) { - if(isnan(value) || isinf(value)) +static inline void calc_colorz(const char *color, char *final, size_t len, calculated_number value) { + int value_is_null = 0; + if(isnan(value) || isinf(value)) { value = 0.0; + value_is_null = 1; + } char color_buffer[256 + 1] = ""; char value_buffer[256 + 1] = ""; @@ -673,7 +723,7 @@ static inline void calc_colorz(const char *color, char *final, size_t len, calcu // colors #define COLOR_STRING_SIZE 100 -void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int value_is_null, int precision) { +void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision) { char label_buffer[LABEL_STRING_SIZE + 1] , value_color_buffer[COLOR_STRING_SIZE + 1] , value_string[VALUE_STRING_SIZE + 1] @@ -688,66 +738,10 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch label_color = "#555"; if(unlikely(!value_color || !*value_color)) - value_color = (value_is_null)?"#999":"#4c1"; - - calc_colorz(value_color, value_color_buffer, COLOR_STRING_SIZE, value, value_is_null); - - if(!fix_value_and_units(value_string, VALUE_STRING_SIZE, value, &units, value_is_null)) { - // we have to print the value - - if(isnan(value) || isinf(value)) - value = 0.0; - - char *separator = ""; - if(unlikely(isalnum(*units))) - separator = " "; - - if(precision < 0) { - int len, lstop = 0, trim_zeros = 1; - - calculated_number abs = value; - if(isless(value, 0)) { - lstop = 1; - abs = -value; - } + value_color = (isnan(value) || isinf(value))?"#999":"#4c1"; - if(isgreaterequal(abs, 1000)) { - len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.0Lf", (long double) value); - trim_zeros = 0; - } - else if(isgreaterequal(abs, 100)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.1Lf", (long double) value); - else if(isgreaterequal(abs, 1)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.2Lf", (long double) value); - else if(isgreaterequal(abs, 0.1)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.3Lf", (long double) value); - else len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.4Lf", (long double) value); - - if(unlikely(trim_zeros)) { - int l; - // remove trailing zeros from the decimal part - for(l = len - 1; l > lstop; l--) { - if(likely(value_string[l] == '0')) { - value_string[l] = '\0'; - len--; - } - - else if(unlikely(value_string[l] == '.')) { - value_string[l] = '\0'; - len--; - break; - } - - else - break; - } - } - - if(len >= 0) - snprintfz(&value_string[len], VALUE_STRING_SIZE - len, "%s%s", separator, units); - } - else { - if(precision > 50) precision = 50; - snprintfz(value_string, VALUE_STRING_SIZE, "%0.*Lf%s%s", precision, (long double) value, separator, units); - } - } + calc_colorz(value_color, value_color_buffer, COLOR_STRING_SIZE, value); + format_value_and_unit(value_string, VALUE_STRING_SIZE, value, units, precision); // we need to copy the label, since verdana11_width may write to it strncpyz(label_buffer, label, LABEL_STRING_SIZE); diff --git a/src/web_buffer_svg.h b/src/web_buffer_svg.h index 1281847e..49f73e44 100644 --- a/src/web_buffer_svg.h +++ b/src/web_buffer_svg.h @@ -1,6 +1,7 @@ #ifndef NETDATA_WEB_BUFFER_SVG_H #define NETDATA_WEB_BUFFER_SVG_H 1 -extern void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int value_is_null, int precision); +extern void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision); +extern char *format_value_and_unit(char *value_string, size_t value_string_len, calculated_number value, const char *units, int precision); #endif /* NETDATA_WEB_BUFFER_SVG_H */ diff --git a/src/web_client.c b/src/web_client.c index 7932a526..5acb44d5 100644 --- a/src/web_client.c +++ b/src/web_client.c @@ -896,7 +896,7 @@ int web_client_api_request_v1_badge(struct web_client *w, char *url) { if(!st) st = rrdset_find_byname(chart); if(!st) { buffer_no_cacheable(w->response.data); - buffer_svg(w->response.data, "chart not found", 0, "", NULL, NULL, 1, -1); + buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1); ret = 200; goto cleanup; } @@ -906,7 +906,7 @@ int web_client_api_request_v1_badge(struct web_client *w, char *url) { rc = rrdcalc_find(st, alarm); if (!rc) { buffer_no_cacheable(w->response.data); - buffer_svg(w->response.data, "alarm not found", 0, "", NULL, NULL, 1, -1); + buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1); ret = 200; goto cleanup; } @@ -1022,14 +1022,13 @@ int web_client_api_request_v1_badge(struct web_client *w, char *url) { units, label_color, value_color, - 0, precision); ret = 200; } else { time_t latest_timestamp = 0; int value_is_null = 1; - calculated_number n = 0; + calculated_number n = NAN; ret = 500; // if the collected value is too old, don't calculate its value @@ -1062,13 +1061,12 @@ int web_client_api_request_v1_badge(struct web_client *w, char *url) { // render the badge buffer_svg(w->response.data, - label, - n * multiply / divide, - units, - label_color, - value_color, - value_is_null, - precision); + label, + (value_is_null)?NAN:(n * multiply / divide), + units, + label_color, + value_color, + precision); } cleanup: diff --git a/web/dashboard.js b/web/dashboard.js index 6fc29420..c53b68f8 100644 --- a/web/dashboard.js +++ b/web/dashboard.js @@ -6075,7 +6075,7 @@ var NETDATA = window.NETDATA || {}; var name = entry.name.replace(/_/g, ' '); var status = entry.status.toLowerCase(); - var title = name + ' = ' + ((value === null)?'NaN':Math.floor(value)).toString() + ' ' + entry.units; + var title = name + ' = ' + entry.value_string.toString(); var tag = entry.alarm_id; var icon = 'images/seo-performance-128.png'; var interaction = false; @@ -6104,7 +6104,7 @@ var NETDATA = window.NETDATA || {}; // console.log('alarm' + entry.unique_id + ' switch to CLEAR from ' + entry.old_status); return; } - title = name + ' back to normal'; + title = name + ' back to normal (' + entry.value_string.toString() + ')'; icon = 'images/check-mark-2-128-green.png' interaction = false; break; diff --git a/web/index.html b/web/index.html index e95e3151..040bd148 100644 --- a/web/index.html +++ b/web/index.html @@ -1855,6 +1855,23 @@ 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', @@ -1876,6 +1893,7 @@ }, align: 'right', valign: 'middle', + visible: false, sortable: true }, { @@ -1884,6 +1902,7 @@ titleTooltip: 'The units of the value of the alarm', align: 'left', valign: 'middle', + visible: false, sortable: true }, {