]> arthur.barton.de Git - netdata.git/commitdiff
alarms status API ready
authorCosta Tsaousis <costa@tsaousis.gr>
Thu, 25 Aug 2016 09:22:56 +0000 (12:22 +0300)
committerCosta Tsaousis <costa@tsaousis.gr>
Thu, 25 Aug 2016 09:22:56 +0000 (12:22 +0300)
src/health.c
src/health.h
src/web_buffer.c
src/web_client.c

index 234717b8897257ae0aa8e03ba1a83f4d10c4472c..746392daeb702695f80df21d4c4b2425805d36d2 100644 (file)
@@ -1414,83 +1414,112 @@ void health_init(void) {
 // ----------------------------------------------------------------------------
 // JSON generation
 
+static inline void health_string2json(BUFFER *wb, const char *prefix, const char *label, const char *value, const char *suffix) {
+    if(value && *value)
+        buffer_sprintf(wb, "%s\"%s\":\"%s\"%s", prefix, label, value, suffix);
+    else
+        buffer_sprintf(wb, "%s\"%s\":null%s", prefix, label, suffix);
+}
+
 static inline void health_rrdcalc2json_nolock(BUFFER *wb, RRDCALC *rc) {
+
     buffer_sprintf(wb,
-           "\t\t\"%s.%s\": {"
+           "\t\t\"%s.%s\": {\n"
                    "\t\t\t\"name\": \"%s\",\n"
                    "\t\t\t\"chart\": \"%s\",\n"
-                   "\t\t\t\"dimensions\": \"%s\",\n"
                    "\t\t\t\"exec\": \"%s\",\n"
                    "\t\t\t\"source\": \"%s\",\n"
-                   "\t\t\t\"calc\": \"%s\",\n"
-                   "\t\t\t\"calc_parsed\": \"%s\",\n"
-                   "\t\t\t\"warn\": \"%s\",\n"
-                   "\t\t\t\"warn_parsed\": \"%s\",\n"
-                   "\t\t\t\"crit\": \"%s\",\n"
-                   "\t\t\t\"crit_parsed\": \"%s\",\n"
-                   "\t\t\t\"value\": %Lf,\n"
-                   "\t\t\t\"value_after\": %lu,\n"
-                   "\t\t\t\"value_before\": %lu,\n"
-                   "\t\t\t\"green\": %Lf,\n"
-                   "\t\t\t\"red\": %Lf,\n"
                    "\t\t\t\"status\": \"%s\",\n"
                    "\t\t\t\"last_status_change\": %lu,\n"
                    "\t\t\t\"last_updated\": %lu,\n"
                    "\t\t\t\"next_update\": %lu,\n"
                    "\t\t\t\"update_every\": %d,\n"
-                   "\t\t\t\"lookup_method\": \"%s\",\n"
-                   "\t\t\t\"lookup_after\": %d,\n"
-                   "\t\t\t\"lookup_before\": %d,\n"
-                   "\t\t\t\"lookup_options\": \""
             , rc->chart, rc->name
             , rc->name
             , rc->chart
-            , rc->dimensions?rc->dimensions:""
             , rc->exec?rc->exec:health_default_exec
             , rc->source
-            , rc->calculation?rc->calculation->source:""
-            , rc->calculation?rc->calculation->parsed_as:""
-            , rc->warning?rc->warning->source:""
-            , rc->warning?rc->warning->parsed_as:""
-            , rc->critical?rc->critical->source:""
-            , rc->critical?rc->critical->parsed_as:""
-            , rc->value
-            , (unsigned long)rc->db_after
-            , (unsigned long)rc->db_before
-            , rc->green
-            , rc->red
             , rrdcalc_status2string(rc->status)
             , (unsigned long)rc->last_status_change
             , (unsigned long)rc->last_updated
             , (unsigned long)rc->next_update
             , rc->update_every
-            , group_method2string(rc->group)
-            , rc->after
-            , rc->before
     );
 
-    buffer_data_options2string(wb, rc->options);
-    buffer_strcat(wb, "\"\n\t}");
+    if(RRDCALC_HAS_DB_LOOKUP(rc)) {
+        if(rc->dimensions && *rc->dimensions)
+            health_string2json(wb, "\t\t\t", "lookup_dimensions", rc->dimensions, ",\n");
+
+        buffer_sprintf(wb,
+                       "\t\t\t\"db_after\": %lu,\n"
+                       "\t\t\t\"db_before\": %lu,\n"
+                       "\t\t\t\"lookup_method\": \"%s\",\n"
+                       "\t\t\t\"lookup_after\": %d,\n"
+                       "\t\t\t\"lookup_before\": %d,\n"
+                       "\t\t\t\"lookup_options\": \"",
+                       (unsigned long) rc->db_after,
+                       (unsigned long) rc->db_before,
+                       group_method2string(rc->group),
+                       rc->after,
+                       rc->before
+        );
+        buffer_data_options2string(wb, rc->options);
+        buffer_strcat(wb, "\",\n");
+    }
+
+    if(rc->calculation) {
+        health_string2json(wb, "\t\t\t", "calc", rc->calculation->source, ",\n");
+        health_string2json(wb, "\t\t\t", "calc_parsed", rc->calculation->parsed_as, ",\n");
+    }
+
+    if(rc->warning) {
+        health_string2json(wb, "\t\t\t", "warn", rc->warning->source, ",\n");
+        health_string2json(wb, "\t\t\t", "warn_parsed", rc->warning->parsed_as, ",\n");
+    }
+
+    if(rc->critical) {
+        health_string2json(wb, "\t\t\t", "crit", rc->critical->source, ",\n");
+        health_string2json(wb, "\t\t\t", "crit_parsed", rc->critical->parsed_as, ",\n");
+    }
+
+    buffer_strcat(wb, "\t\t\t\"green\":");
+    buffer_rrd_value(wb, rc->green);
+    buffer_strcat(wb, ",\n");
+
+    buffer_strcat(wb, "\t\t\t\"red\":");
+    buffer_rrd_value(wb, rc->red);
+    buffer_strcat(wb, ",\n");
+
+    buffer_strcat(wb, "\t\t\t\"value\":");
+    buffer_rrd_value(wb, rc->value);
+    buffer_strcat(wb, "\n");
+
+    buffer_strcat(wb, "\t\t}");
 }
 
 //void health_rrdcalctemplate2json_nolock(BUFFER *wb, RRDCALCTEMPLATE *rt) {
 //
 //}
 
-void health_json(RRDHOST *host, BUFFER *wb) {
+void health_alarms2json(RRDHOST *host, BUFFER *wb) {
+    int i;
     rrdhost_rdlock(&localhost);
 
-    buffer_strcat(wb, "{\n\t\"alarms\": {");
+    buffer_strcat(wb, "{\n\t\"alarms\": {\n");
     RRDCALC *rc;
-    for(rc = host->alarms; rc ; rc = rc->next)
+    for(i = 0, rc = host->alarms; rc ; rc = rc->next, i++) {
+        if(likely(i)) buffer_strcat(wb, ",\n");
         health_rrdcalc2json_nolock(wb, rc);
+    }
 
-    buffer_strcat(wb, "\n},\n\t\"templates\": {");
+    buffer_strcat(wb, "\n\t},\n\t\"templates\": {");
 
 //    RRDCALCTEMPLATE *rt;
 //    for(rt = host->templates; rt ; rt = rt->next)
 //        health_rrdcalctemplate2json_nolock(wb, rt);
 
+    buffer_strcat(wb, "\n\t}");
+    buffer_sprintf(wb, ",\n\t\"now\": %lu", (unsigned long)time(NULL));
     buffer_strcat(wb, "\n}\n");
     rrdhost_unlock(&localhost);
 }
index 54a8ec63fea8b7dbee37b287372a3fa236fdc024..045ddf1a81bfa8de0728ff373dccf1ac1c3c0377 100644 (file)
@@ -263,5 +263,6 @@ extern void *health_main(void *ptr);
 extern void health_reload(void);
 
 extern int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, calculated_number *result);
+extern void health_alarms2json(RRDHOST *host, BUFFER *wb);
 
 #endif //NETDATA_HEALTH_H
index 5b4f24623ba86ef230fc1c90e95a2bf283d34e94..b2285fadd229e6c7992733c91d8f64944bf9aa3b 100644 (file)
@@ -117,7 +117,7 @@ void buffer_strcat(BUFFER *wb, const char *txt)
     buffer_need_bytes(wb, 1);
 
     char *s = &wb->buffer[wb->len], *start, *end = &wb->buffer[wb->size];
-    long len = wb->len;
+    size_t len = wb->len;
 
     start = s;
     while(*txt && s != end)
@@ -213,7 +213,13 @@ void buffer_sprintf(BUFFER *wb, const char *fmt, ...)
 void buffer_rrd_value(BUFFER *wb, calculated_number value)
 {
     buffer_need_bytes(wb, 50);
-    wb->len += print_calculated_number(&wb->buffer[wb->len], value);
+
+    if(isnan(value) || isinf(value)) {
+        buffer_strcat(wb, "null");
+        return;
+    }
+    else
+        wb->len += print_calculated_number(&wb->buffer[wb->len], value);
 
     // terminate it
     buffer_need_bytes(wb, 1);
index eebb73ac7928125b5d73f42ea4a2a4a630e3e2af..7f74ac5a292baae569f48174c42edb48bf43ab4a 100644 (file)
@@ -617,6 +617,9 @@ uint32_t web_client_api_request_v1_data_google_format(char *name)
 
 const char *group_method2string(int group) {
     switch(group) {
+        case GROUP_UNDEFINED:
+            return "";
+
         case GROUP_AVERAGE:
             return "average";
 
@@ -657,6 +660,16 @@ int web_client_api_request_v1_data_group(char *name, int def)
     return def;
 }
 
+int web_client_api_request_v1_alarms(struct web_client *w, char *url)
+{
+    (void)url;
+
+    buffer_flush(w->response.data);
+    w->response.data->contenttype = CT_APPLICATION_JSON;
+    health_alarms2json(&localhost, w->response.data);
+    return 200;
+}
+
 int web_client_api_request_v1_charts(struct web_client *w, char *url)
 {
     if(url) { ; }
@@ -713,7 +726,7 @@ cleanup:
     return ret;
 }
 
-int web_client_api_v1_badge(struct web_client *w, char *url) {
+int web_client_api_request_v1_badge(struct web_client *w, char *url) {
     int ret = 400;
     buffer_flush(w->response.data);
 
@@ -1311,7 +1324,7 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
 }
 
 int web_client_api_request_v1(struct web_client *w, char *url) {
-    static uint32_t hash_data = 0, hash_chart = 0, hash_charts = 0, hash_registry = 0, hash_badge = 0;
+    static uint32_t hash_data = 0, hash_chart = 0, hash_charts = 0, hash_registry = 0, hash_badge = 0, hash_alarms = 0;
 
     if(unlikely(hash_data == 0)) {
         hash_data = simple_hash("data");
@@ -1319,6 +1332,7 @@ int web_client_api_request_v1(struct web_client *w, char *url) {
         hash_charts = simple_hash("charts");
         hash_registry = simple_hash("registry");
         hash_badge = simple_hash("badge.svg");
+        hash_alarms = simple_hash("alarms");
     }
 
     // get the command
@@ -1340,7 +1354,10 @@ int web_client_api_request_v1(struct web_client *w, char *url) {
             return web_client_api_request_v1_registry(w, url);
 
         else if(hash == hash_badge && !strcmp(tok, "badge.svg"))
-            return web_client_api_v1_badge(w, url);
+            return web_client_api_request_v1_badge(w, url);
+
+        else if(hash == hash_alarms && !strcmp(tok, "alarms"))
+            return web_client_api_request_v1_alarms(w, url);
 
         else {
             buffer_flush(w->response.data);