@cryptotaxi247 / netdata-1 / commits / 2b3bb61fb

extended the badges API to support rendering alarms

Costa Tsaousis committed Aug 21, 2016 at 20:04 UTC 2b3bb61fb38fba736e20c2a713f1a00ba571047a
4 files changed +101 -19
src/health.c
+16
@@ -420,6 +420,10 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) {
420
421 rc->rrdset = st;
422
423 + rc->rrdset_next = st->alarms;
424 + rc->rrdset_prev = NULL;
425 + st->alarms = rc;
426 +
427 if(rc->update_every < rc->rrdset->update_every) {
428 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);
429 rc->update_every = rc->rrdset->update_every;
@@ -511,6 +515,18 @@ inline void rrdsetcalc_unlink(RRDCALC *rc) {
515 // it will be applied automatically
516 }
517
518 +RRDCALC *rrdcalc_find(RRDSET *st, const char *name) {
519 + RRDCALC *rc;
520 + uint32_t hash = simple_hash(name);
521 +
522 + for( rc = st->alarms; rc ; rc = rc->rrdset_next ) {
523 + if(rc->hash == hash && !strcmp(rc->name, name))
524 + return rc;
525 + }
526 +
527 + return NULL;
528 +}
529 +
530 static inline int rrdcalc_exists(RRDHOST *host, const char *name, uint32_t hash) {
531 RRDCALC *rc;
532
src/health.h
+1
@@ -256,6 +256,7 @@ extern void rrddimvar_free(RRDDIMVAR *rs);
256 extern void rrdsetcalc_link_matching(RRDSET *st);
257 extern void rrdsetcalc_unlink(RRDCALC *rc);
258 extern void rrdcalctemplate_link_matching(RRDSET *st);
259 +extern RRDCALC *rrdcalc_find(RRDSET *st, const char *name);
260
261 extern void health_init(void);
262 extern void *health_main(void *ptr);
src/web_client.c
+77 -19
@@ -644,7 +644,8 @@ int web_client_api_v1_badge(struct web_client *w, char *url) {
644 , *label_color = NULL
645 , *value_color = NULL
646 , *refresh_str = NULL
647 - , *precision_str = NULL;
647 + , *precision_str = NULL
648 + , *alarm = NULL;
649
650 int group = GROUP_AVERAGE;
651 uint32_t options = 0x00000000;
@@ -687,6 +688,7 @@ int web_client_api_v1_badge(struct web_client *w, char *url) {
688 else if(!strcmp(name, "divide")) divide_str = value;
689 else if(!strcmp(name, "refresh")) refresh_str = value;
690 else if(!strcmp(name, "precision")) precision_str = value;
691 + else if(!strcmp(name, "alarm")) alarm = value;
692 }
693
694 if(!chart || !*chart) {
@@ -702,6 +704,16 @@ int web_client_api_v1_badge(struct web_client *w, char *url) {
704 goto cleanup;
705 }
706
707 + RRDCALC *rc = NULL;
708 + if(alarm) {
709 + rc = rrdcalc_find(st, alarm);
710 + if (!rc) {
711 + buffer_svg(w->response.data, "alarm not found", 0, "", NULL, NULL, 1, -1);
712 + ret = 200;
713 + goto cleanup;
714 + }
715 + }
716 +
717 long long multiply = (multiply_str && *multiply_str )?atol(multiply_str):1;
718 long long divide = (divide_str && *divide_str )?atol(divide_str):1;
719 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) {
727 int refresh = 0;
728 if(refresh_str && *refresh_str) {
729 if(!strcmp(refresh_str, "auto")) {
718 - if(options & RRDR_OPTION_NOT_ALIGNED)
730 + if(rc) refresh = rc->update_every;
731 + else if(options & RRDR_OPTION_NOT_ALIGNED)
732 refresh = st->update_every;
733 else {
734 refresh = (before - after);
@@ -729,7 +742,9 @@ int web_client_api_v1_badge(struct web_client *w, char *url) {
742 }
743
744 if(!label) {
732 - if(dimensions) {
745 + if(alarm)
746 + label = alarm;
747 + else if(dimensions) {
748 const char *dim = buffer_tostring(dimensions);
749 if(*dim == '|') dim++;
750 label = dim;
@@ -744,9 +759,10 @@ int web_client_api_v1_badge(struct web_client *w, char *url) {
759 units = st->units;
760 }
761
747 - 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'"
762 + 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'"
763 , w->id
764 , chart
765 + , alarm?alarm:""
766 , (dimensions)?buffer_tostring(dimensions):""
767 , after
768 , before
@@ -755,26 +771,68 @@ int web_client_api_v1_badge(struct web_client *w, char *url) {
771 , options
772 );
773
758 - time_t latest_timestamp = 0;
759 - int value_is_null = 1;
760 - calculated_number n = 0;
761 - ret = 500;
774 + if(rc) {
775 + calculated_number n = rc->value;
776 + if(isnan(n) || isinf(n)) n = 0;
777 +
778 + if (refresh > 0)
779 + buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
780 +
781 + if(!value_color) {
782 + switch(rc->status) {
783 + case RRDCALC_STATUS_CRITICAL:
784 + value_color = "red";
785 + break;
786 +
787 + case RRDCALC_STATUS_WARNING:
788 + value_color = "orange";
789 + break;
790 +
791 + case RRDCALC_STATUS_CLEAR:
792 + value_color = "brightgreen";
793 + break;
794 +
795 + case RRDCALC_STATUS_UNDEFINED:
796 + value_color = "lightgrey";
797 + break;
798
763 - // if the collected value is too old, don't calculate its value
764 - if(rrdset_last_entry_t(st) >= (time(NULL) - (st->update_every * st->gap_when_lost_iterations_above)))
765 - ret = rrd2value(st, w->response.data, &n, (dimensions)?buffer_tostring(dimensions):NULL, points, after, before, group, options, &latest_timestamp, &value_is_null);
799 + case RRDCALC_STATUS_UNINITIALIZED:
800 + value_color = "#000";
801 + break;
802
767 - // if the value cannot be calculated, show empty badge
768 - if(ret != 200) {
769 - value_is_null = 1;
770 - n = 0;
803 + default:
804 + value_color = "grey";
805 + break;
806 + }
807 + }
808 +
809 + buffer_svg(w->response.data, label, rc->value * multiply / divide, units, label_color, value_color, 0, precision);
810 ret = 200;
811 }
773 - else if(refresh > 0)
774 - buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
812 + else {
813 + time_t latest_timestamp = 0;
814 + int value_is_null = 1;
815 + calculated_number n = 0;
816 + ret = 500;
817
776 - // render the badge
777 - buffer_svg(w->response.data, label, n * multiply / divide, units, label_color, value_color, value_is_null, precision);
818 + // if the collected value is too old, don't calculate its value
819 + if (rrdset_last_entry_t(st) >= (time(NULL) - (st->update_every * st->gap_when_lost_iterations_above)))
820 + ret = rrd2value(st, w->response.data, &n, (dimensions) ? buffer_tostring(dimensions) : NULL, points, after,
821 + before, group, options, &latest_timestamp, &value_is_null);
822 +
823 + // if the value cannot be calculated, show empty badge
824 + if (ret != 200) {
825 + value_is_null = 1;
826 + n = 0;
827 + ret = 200;
828 + }
829 + else if (refresh > 0)
830 + buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
831 +
832 + // render the badge
833 + buffer_svg(w->response.data, label, n * multiply / divide, units, label_color, value_color, value_is_null,
834 + precision);
835 + }
836
837 cleanup:
838 if(dimensions)
web/netdata-swagger.yaml
+7
@@ -157,6 +157,13 @@ paths:
157 format: 'as returned by /charts'
158 allowEmptyValue: false
159 default: system.cpu
160 + - name: alarm
161 + in: query
162 + description: 'the name of an alarm linked to the chart'
163 + required: false
164 + type: string
165 + format: 'any text'
166 + allowEmptyValue: true
167 - name: dimension
168 in: query
169 description: 'zero, one or more dimension ids, as returned by the /chart call.'