From: Costa Tsaousis Date: Sun, 21 Aug 2016 17:04:28 +0000 (+0300) Subject: extended the badges API to support rendering alarms X-Git-Tag: v1.3.0~20^2~2 X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2b3bb61fb38fba736e20c2a713f1a00ba571047a;p=netdata.git extended the badges API to support rendering alarms --- diff --git a/src/health.c b/src/health.c index bf37b013..2e5f4aed 100644 --- a/src/health.c +++ b/src/health.c @@ -420,6 +420,10 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) { rc->rrdset = st; + rc->rrdset_next = st->alarms; + rc->rrdset_prev = NULL; + st->alarms = rc; + if(rc->update_every < rc->rrdset->update_every) { error("Health alarm '%s.%s' has update every %d, less than chart update every %d. Setting alarm update frequency to %d.", rc->rrdset->id, rc->name, rc->update_every, rc->rrdset->update_every, rc->rrdset->update_every); rc->update_every = rc->rrdset->update_every; @@ -511,6 +515,18 @@ inline void rrdsetcalc_unlink(RRDCALC *rc) { // it will be applied automatically } +RRDCALC *rrdcalc_find(RRDSET *st, const char *name) { + RRDCALC *rc; + uint32_t hash = simple_hash(name); + + for( rc = st->alarms; rc ; rc = rc->rrdset_next ) { + if(rc->hash == hash && !strcmp(rc->name, name)) + return rc; + } + + return NULL; +} + static inline int rrdcalc_exists(RRDHOST *host, const char *name, uint32_t hash) { RRDCALC *rc; diff --git a/src/health.h b/src/health.h index a269699a..5bf6adac 100644 --- a/src/health.h +++ b/src/health.h @@ -256,6 +256,7 @@ extern void rrddimvar_free(RRDDIMVAR *rs); extern void rrdsetcalc_link_matching(RRDSET *st); extern void rrdsetcalc_unlink(RRDCALC *rc); extern void rrdcalctemplate_link_matching(RRDSET *st); +extern RRDCALC *rrdcalc_find(RRDSET *st, const char *name); extern void health_init(void); extern void *health_main(void *ptr); diff --git a/src/web_client.c b/src/web_client.c index 6b454b78..804ea980 100644 --- a/src/web_client.c +++ b/src/web_client.c @@ -644,7 +644,8 @@ int web_client_api_v1_badge(struct web_client *w, char *url) { , *label_color = NULL , *value_color = NULL , *refresh_str = NULL - , *precision_str = NULL; + , *precision_str = NULL + , *alarm = NULL; int group = GROUP_AVERAGE; uint32_t options = 0x00000000; @@ -687,6 +688,7 @@ int web_client_api_v1_badge(struct web_client *w, char *url) { else if(!strcmp(name, "divide")) divide_str = value; else if(!strcmp(name, "refresh")) refresh_str = value; else if(!strcmp(name, "precision")) precision_str = value; + else if(!strcmp(name, "alarm")) alarm = value; } if(!chart || !*chart) { @@ -702,6 +704,16 @@ int web_client_api_v1_badge(struct web_client *w, char *url) { goto cleanup; } + RRDCALC *rc = NULL; + if(alarm) { + rc = rrdcalc_find(st, alarm); + if (!rc) { + buffer_svg(w->response.data, "alarm not found", 0, "", NULL, NULL, 1, -1); + ret = 200; + goto cleanup; + } + } + long long multiply = (multiply_str && *multiply_str )?atol(multiply_str):1; long long divide = (divide_str && *divide_str )?atol(divide_str):1; long long before = (before_str && *before_str )?atol(before_str):0; @@ -715,7 +727,8 @@ int web_client_api_v1_badge(struct web_client *w, char *url) { int refresh = 0; if(refresh_str && *refresh_str) { if(!strcmp(refresh_str, "auto")) { - if(options & RRDR_OPTION_NOT_ALIGNED) + if(rc) refresh = rc->update_every; + else if(options & RRDR_OPTION_NOT_ALIGNED) refresh = st->update_every; else { refresh = (before - after); @@ -729,7 +742,9 @@ int web_client_api_v1_badge(struct web_client *w, char *url) { } if(!label) { - if(dimensions) { + if(alarm) + label = alarm; + else if(dimensions) { const char *dim = buffer_tostring(dimensions); if(*dim == '|') dim++; label = dim; @@ -744,9 +759,10 @@ int web_client_api_v1_badge(struct web_client *w, char *url) { units = st->units; } - debug(D_WEB_CLIENT, "%llu: API command 'badge.svg' for chart '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', options '0x%08x'" + debug(D_WEB_CLIENT, "%llu: API command 'badge.svg' for chart '%s', alarm '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', options '0x%08x'" , w->id , chart + , alarm?alarm:"" , (dimensions)?buffer_tostring(dimensions):"" , after , before @@ -755,26 +771,68 @@ int web_client_api_v1_badge(struct web_client *w, char *url) { , options ); - time_t latest_timestamp = 0; - int value_is_null = 1; - calculated_number n = 0; - ret = 500; + if(rc) { + calculated_number n = rc->value; + if(isnan(n) || isinf(n)) n = 0; + + if (refresh > 0) + buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh); + + if(!value_color) { + switch(rc->status) { + case RRDCALC_STATUS_CRITICAL: + value_color = "red"; + break; + + case RRDCALC_STATUS_WARNING: + value_color = "orange"; + break; + + case RRDCALC_STATUS_CLEAR: + value_color = "brightgreen"; + break; + + case RRDCALC_STATUS_UNDEFINED: + value_color = "lightgrey"; + break; - // if the collected value is too old, don't calculate its value - if(rrdset_last_entry_t(st) >= (time(NULL) - (st->update_every * st->gap_when_lost_iterations_above))) - ret = rrd2value(st, w->response.data, &n, (dimensions)?buffer_tostring(dimensions):NULL, points, after, before, group, options, &latest_timestamp, &value_is_null); + case RRDCALC_STATUS_UNINITIALIZED: + value_color = "#000"; + break; - // if the value cannot be calculated, show empty badge - if(ret != 200) { - value_is_null = 1; - n = 0; + default: + value_color = "grey"; + break; + } + } + + buffer_svg(w->response.data, label, rc->value * multiply / divide, units, label_color, value_color, 0, precision); ret = 200; } - else if(refresh > 0) - buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh); + else { + time_t latest_timestamp = 0; + int value_is_null = 1; + calculated_number n = 0; + ret = 500; - // render the badge - buffer_svg(w->response.data, label, n * multiply / divide, units, label_color, value_color, value_is_null, precision); + // if the collected value is too old, don't calculate its value + if (rrdset_last_entry_t(st) >= (time(NULL) - (st->update_every * st->gap_when_lost_iterations_above))) + ret = rrd2value(st, w->response.data, &n, (dimensions) ? buffer_tostring(dimensions) : NULL, points, after, + before, group, options, &latest_timestamp, &value_is_null); + + // if the value cannot be calculated, show empty badge + if (ret != 200) { + value_is_null = 1; + n = 0; + ret = 200; + } + else if (refresh > 0) + buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh); + + // render the badge + buffer_svg(w->response.data, label, n * multiply / divide, units, label_color, value_color, value_is_null, + precision); + } cleanup: if(dimensions) diff --git a/web/netdata-swagger.yaml b/web/netdata-swagger.yaml index 5d01a73f..c1049b12 100644 --- a/web/netdata-swagger.yaml +++ b/web/netdata-swagger.yaml @@ -157,6 +157,13 @@ paths: format: 'as returned by /charts' allowEmptyValue: false default: system.cpu + - name: alarm + in: query + description: 'the name of an alarm linked to the chart' + required: false + type: string + format: 'any text' + allowEmptyValue: true - name: dimension in: query description: 'zero, one or more dimension ids, as returned by the /chart call.'