]> arthur.barton.de Git - netdata.git/commitdiff
added alarm_variables API call that returns all the available variables for a chart
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Sat, 12 Nov 2016 22:08:39 +0000 (00:08 +0200)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Sat, 12 Nov 2016 22:08:39 +0000 (00:08 +0200)
src/avl.c
src/avl.h
src/health.c
src/health.h
src/rrd.c
src/unit_test.c
src/web_client.c

index 324afeebbad76ad96a17a747a48bde9f5e5a19fa..7efbf6da39f7d78f9aac9fe91cfdce96df2ff389 100644 (file)
--- a/src/avl.c
+++ b/src/avl.c
@@ -283,18 +283,18 @@ avl *avl_remove(avl_tree *tree, avl *item) {
 // ---------------------------
 // traversing
 
-void avl_walker(avl *node, void (*callback)(void *)) {
+void avl_walker(avl *node, void (*callback)(void *entry, void *data), void *data) {
     if(node->avl_link[0])
-        avl_walker(node->avl_link[0], callback);
+        avl_walker(node->avl_link[0], callback, data);
 
-    callback(node);
+    callback(node, data);
 
     if(node->avl_link[1])
-        avl_walker(node->avl_link[1], callback);
+        avl_walker(node->avl_link[1], callback, data);
 }
 
-void avl_traverse(avl_tree *t, void (*callback)(void *)) {
-    avl_walker(t->root, callback);
+void avl_traverse(avl_tree *t, void (*callback)(void *entry, void *data), void *data) {
+    avl_walker(t->root, callback, data);
 }
 
 // ---------------------------
@@ -372,9 +372,9 @@ avl *avl_insert_lock(avl_tree_lock *t, avl *a) {
     return ret;
 }
 
-void avl_traverse_lock(avl_tree_lock *t, void (*callback)(void *)) {
+void avl_traverse_lock(avl_tree_lock *t, void (*callback)(void *entry, void *data), void *data) {
     avl_read_lock(t);
-    avl_traverse(&t->avl_tree, callback);
+    avl_traverse(&t->avl_tree, callback, data);
     avl_unlock(t);
 }
 
index 973d68fb1151ec3e67ce53ccac5cd4de3ad0348c..1ca687be510b514a000cfc0b08a257e7d8a1c660 100644 (file)
--- a/src/avl.h
+++ b/src/avl.h
@@ -80,7 +80,7 @@ void avl_init_lock(avl_tree_lock *t, int (*compar)(void *a, void *b));
 void avl_init(avl_tree *t, int (*compar)(void *a, void *b));
 
 
-void avl_traverse_lock(avl_tree_lock *t, void (*callback)(void *));
-void avl_traverse(avl_tree *t, void (*callback)(void *));
+void avl_traverse_lock(avl_tree_lock *t, void (*callback)(void *entry, void *data), void *data);
+void avl_traverse(avl_tree *t, void (*callback)(void *entry, void *data), void *data);
 
 #endif /* avl.h */
index 3533064e5d3c9b55aea02fda365670f1fb6518f3..5dc6586d3e7b19ef913dc4232cf57d858b710da1 100644 (file)
@@ -536,7 +536,7 @@ static inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *
 // ----------------------------------------------------------------------------
 // RRDVAR lookup
 
-calculated_number rrdvar2number(RRDVAR *rv) {
+static calculated_number rrdvar2number(RRDVAR *rv) {
     switch(rv->type) {
         case RRDVAR_TYPE_CALCULATED: {
             calculated_number *n = (calculated_number *)rv->value;
@@ -569,11 +569,6 @@ calculated_number rrdvar2number(RRDVAR *rv) {
     }
 }
 
-void dump_variable(void *data) {
-    RRDVAR *rv = (RRDVAR *)data;
-    debug(D_HEALTH, "%50s : %20.5Lf", rv->name, rrdvar2number(rv));
-}
-
 int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, calculated_number *result) {
     RRDSET *st = rc->rrdset;
     RRDVAR *rv;
@@ -598,18 +593,48 @@ int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, cal
         return 1;
     }
 
-    debug(D_HEALTH, "Available local chart '%s' variables:", st->id);
-    avl_traverse_lock(&st->variables_root_index, dump_variable);
+    return 0;
+}
 
-    debug(D_HEALTH, "Available family '%s' variables:", st->rrdfamily->family);
-    avl_traverse_lock(&st->rrdfamily->variables_root_index, dump_variable);
+// ----------------------------------------------------------------------------
+// RRDVAR to JSON
 
-    debug(D_HEALTH, "Available host '%s' variables:", st->rrdhost->hostname);
-    avl_traverse_lock(&st->rrdhost->variables_root_index, dump_variable);
+struct variable2json_helper {
+    BUFFER *buf;
+    size_t counter;
+};
 
-    return 0;
+static void single_variable2json(void *entry, void *data) {
+    struct variable2json_helper *helper = (struct variable2json_helper *)data;
+    RRDVAR *rv = (RRDVAR *)entry;
+    calculated_number value = rrdvar2number(rv);
+
+    if(unlikely(isnan(value) || isinf(value)))
+        buffer_sprintf(helper->buf, "%s\n\t\t\"%s\": null", helper->counter?",":"", rv->name);
+    else
+        buffer_sprintf(helper->buf, "%s\n\t\t\"%s\": %0.5Lf", helper->counter?",":"", rv->name, (long double)value);
+
+    helper->counter++;
 }
 
+void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf) {
+    struct variable2json_helper helper = {
+            .buf = buf,
+            .counter = 0
+    };
+
+    buffer_sprintf(buf, "{\n\t\"chart\": \"%s.%s\",\n\t\"chart_name\": \"%s.%s\",\n\t\"chart_variables\": {", st->type, st->id, st->type, st->name);
+    avl_traverse_lock(&st->variables_root_index, single_variable2json, (void *)&helper);
+    buffer_sprintf(buf, "\n\t},\n\t\"family\": \"%s\",\n\t\"family_variables\": {", st->family);
+    helper.counter = 0;
+    avl_traverse_lock(&st->rrdfamily->variables_root_index, single_variable2json, (void *)&helper);
+    buffer_sprintf(buf, "\n\t},\n\t\"host\": \"%s\",\n\t\"host_variables\": {", st->rrdhost->hostname);
+    helper.counter = 0;
+    avl_traverse_lock(&st->rrdhost->variables_root_index, single_variable2json, (void *)&helper);
+    buffer_strcat(buf, "\n\t}\n}\n");
+}
+
+
 // ----------------------------------------------------------------------------
 // RRDDIMVAR management
 // DIMENSION VARIABLES
index dbc50737b57a6b035ebd145c6936abfa650c258a..57096c6b3a8e8c25a19892f7e5051683f00c7c2e 100644 (file)
@@ -350,4 +350,6 @@ extern int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *
 extern void health_alarms2json(RRDHOST *host, BUFFER *wb, int all);
 extern void health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after);
 
+void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf);
+
 #endif //NETDATA_HEALTH_H
index 1b563faa3100b90283d28e629fa6d7cdf3680e95..5b218fa81c125ab6b853548f76751b178c7e4606 100644 (file)
--- a/src/rrd.c
+++ b/src/rrd.c
@@ -353,6 +353,9 @@ char *rrdset_strncpyz_name(char *to, const char *from, size_t length)
 
 void rrdset_set_name(RRDSET *st, const char *name)
 {
+    if(unlikely(st->name && !strcmp(st->name, name)))
+        return;
+
     debug(D_RRD_CALLS, "rrdset_set_name() old: %s, new: %s", st->name, name);
 
     char b[CONFIG_MAX_VALUE + 1];
@@ -765,7 +768,10 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
 
 void rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name)
 {
-    debug(D_RRD_CALLS, "rrddim_set_name() %s.%s", st->name, rd->name);
+    if(unlikely(rd->name && !strcmp(rd->name, name)))
+        return;
+
+    debug(D_RRD_CALLS, "rrddim_set_name() from %s.%s to %s.%s", st->name, rd->name, st->name, name);
 
     char varname[CONFIG_MAX_NAME + 1];
     snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
index af4ebd2c36816de1164e5ff8b62fdc24ed5a9e20..139e99755bdf036a95569a507f39ef24a9fc416b 100644 (file)
@@ -975,9 +975,9 @@ int run_test(struct test *test)
     return errors;
 }
 
-void test_variable_renames(void) {
+static int test_variable_renames(void) {
     fprintf(stderr, "Creating chart\n");
-    RRDSET *st = rrdset_create("netdata", "CHARTID1", NULL, "netdata", NULL, "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE);
+    RRDSET *st = rrdset_create("chart", "ID", NULL, "family", "context", "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE);
     fprintf(stderr, "Created chart with id '%s', name '%s'\n", st->id, st->name);
 
     fprintf(stderr, "Creating dimension DIM1\n");
@@ -1011,12 +1011,18 @@ void test_variable_renames(void) {
     fprintf(stderr, "Renaming dimension DIM2 to DIM2NAME2\n");
     rrddim_set_name(st, rd2, "DIM2NAME2");
     fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd2->id, rd2->name);
+
+    BUFFER *buf = buffer_create(1);
+    health_api_v1_chart_variables2json(st, buf);
+    fprintf(stderr, "%s", buffer_tostring(buf));
+    buffer_free(buf);
+    return 1;
 }
 
 int run_all_mockup_tests(void)
 {
-    test_variable_renames();
-    exit(1);
+    if(!test_variable_renames())
+        return 1;
 
     if(run_test(&test1))
         return 1;
index c51767bad1576d8608032191a551f6f90df5cec2..2b2402f4ec80455bf6777f949bf6ff6d49641720 100644 (file)
@@ -700,17 +700,7 @@ int web_client_api_request_v1_alarm_log(struct web_client *w, char *url)
     return 200;
 }
 
-int web_client_api_request_v1_charts(struct web_client *w, char *url)
-{
-    (void)url;
-
-    buffer_flush(w->response.data);
-    w->response.data->contenttype = CT_APPLICATION_JSON;
-    rrd_stats_api_v1_charts(w->response.data);
-    return 200;
-}
-
-int web_client_api_request_v1_chart(struct web_client *w, char *url)
+int web_client_api_request_single_chart(struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf))
 {
     int ret = 400;
     char *chart = NULL;
@@ -749,13 +739,33 @@ int web_client_api_request_v1_chart(struct web_client *w, char *url)
     }
 
     w->response.data->contenttype = CT_APPLICATION_JSON;
-    rrd_stats_api_v1_chart(st, w->response.data);
+    callback(st, w->response.data);
     return 200;
 
-cleanup:
+    cleanup:
     return ret;
 }
 
+int web_client_api_request_v1_alarm_variables(struct web_client *w, char *url)
+{
+    return web_client_api_request_single_chart(w, url, health_api_v1_chart_variables2json);
+}
+
+int web_client_api_request_v1_charts(struct web_client *w, char *url)
+{
+    (void)url;
+
+    buffer_flush(w->response.data);
+    w->response.data->contenttype = CT_APPLICATION_JSON;
+    rrd_stats_api_v1_charts(w->response.data);
+    return 200;
+}
+
+int web_client_api_request_v1_chart(struct web_client *w, char *url)
+{
+    return web_client_api_request_single_chart(w, url, rrd_stats_api_v1_chart);
+}
+
 int web_client_api_request_v1_badge(struct web_client *w, char *url) {
     int ret = 400;
     buffer_flush(w->response.data);
@@ -1405,7 +1415,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, hash_alarms = 0, hash_alarm_log = 0;
+    static uint32_t hash_data = 0, hash_chart = 0, hash_charts = 0, hash_registry = 0, hash_badge = 0, hash_alarms = 0, hash_alarm_log = 0, hash_alarm_variables = 0;
 
     if(unlikely(hash_data == 0)) {
         hash_data = simple_hash("data");
@@ -1415,6 +1425,7 @@ int web_client_api_request_v1(struct web_client *w, char *url) {
         hash_badge = simple_hash("badge.svg");
         hash_alarms = simple_hash("alarms");
         hash_alarm_log = simple_hash("alarm_log");
+        hash_alarm_variables = simple_hash("alarm_variables");
     }
 
     // get the command
@@ -1444,6 +1455,9 @@ int web_client_api_request_v1(struct web_client *w, char *url) {
         else if(hash == hash_alarm_log && !strcmp(tok, "alarm_log"))
             return web_client_api_request_v1_alarm_log(w, url);
 
+        else if(hash == hash_alarm_variables && !strcmp(tok, "alarm_variables"))
+            return web_client_api_request_v1_alarm_variables(w, url);
+
         else {
             buffer_flush(w->response.data);
             buffer_sprintf(w->response.data, "Unsupported v1 API command: %s", tok);