added alarm_variables API call that returns all the available variables for a chart
Costa Tsaousis (ktsaou) committed
Nov 13, 2016 at 00:08 UTC
7ee54c4901ea66bd6f43dd04298449e5704ae6c0
7 files changed
+95
-42
src/avl.c
+8
-8
@@ -283,18 +283,18 @@ avl *avl_remove(avl_tree *tree, avl *item) {
283
// ---------------------------
284
// traversing
285
286
-void avl_walker(avl *node, void (*callback)(void *)) {
286
+void avl_walker(avl *node, void (*callback)(void *entry, void *data), void *data) {
287
if(node->avl_link[0])
288
- avl_walker(node->avl_link[0], callback);
288
+ avl_walker(node->avl_link[0], callback, data);
289
290
- callback(node);
290
+ callback(node, data);
291
292
if(node->avl_link[1])
293
- avl_walker(node->avl_link[1], callback);
293
+ avl_walker(node->avl_link[1], callback, data);
294
}
295
296
-void avl_traverse(avl_tree *t, void (*callback)(void *)) {
297
- avl_walker(t->root, callback);
296
+void avl_traverse(avl_tree *t, void (*callback)(void *entry, void *data), void *data) {
297
+ avl_walker(t->root, callback, data);
298
}
299
300
// ---------------------------
@@ -372,9 +372,9 @@ avl *avl_insert_lock(avl_tree_lock *t, avl *a) {
372
return ret;
373
}
374
375
-void avl_traverse_lock(avl_tree_lock *t, void (*callback)(void *)) {
375
+void avl_traverse_lock(avl_tree_lock *t, void (*callback)(void *entry, void *data), void *data) {
376
avl_read_lock(t);
377
- avl_traverse(&t->avl_tree, callback);
377
+ avl_traverse(&t->avl_tree, callback, data);
378
avl_unlock(t);
379
}
380
src/avl.h
+2
-2
@@ -80,7 +80,7 @@ void avl_init_lock(avl_tree_lock *t, int (*compar)(void *a, void *b));
80
void avl_init(avl_tree *t, int (*compar)(void *a, void *b));
81
82
83
-void avl_traverse_lock(avl_tree_lock *t, void (*callback)(void *));
84
-void avl_traverse(avl_tree *t, void (*callback)(void *));
83
+void avl_traverse_lock(avl_tree_lock *t, void (*callback)(void *entry, void *data), void *data);
84
+void avl_traverse(avl_tree *t, void (*callback)(void *entry, void *data), void *data);
85
86
#endif /* avl.h */
src/health.c
+38
-13
@@ -536,7 +536,7 @@ static inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *
536
// ----------------------------------------------------------------------------
537
// RRDVAR lookup
538
539
-calculated_number rrdvar2number(RRDVAR *rv) {
539
+static calculated_number rrdvar2number(RRDVAR *rv) {
540
switch(rv->type) {
541
case RRDVAR_TYPE_CALCULATED: {
542
calculated_number *n = (calculated_number *)rv->value;
@@ -569,11 +569,6 @@ calculated_number rrdvar2number(RRDVAR *rv) {
569
}
570
}
571
572
-void dump_variable(void *data) {
573
- RRDVAR *rv = (RRDVAR *)data;
574
- debug(D_HEALTH, "%50s : %20.5Lf", rv->name, rrdvar2number(rv));
575
-}
576
-
572
int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, calculated_number *result) {
573
RRDSET *st = rc->rrdset;
574
RRDVAR *rv;
@@ -598,18 +593,48 @@ int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, cal
593
return 1;
594
}
595
601
- debug(D_HEALTH, "Available local chart '%s' variables:", st->id);
602
- avl_traverse_lock(&st->variables_root_index, dump_variable);
596
+ return 0;
597
+}
598
604
- debug(D_HEALTH, "Available family '%s' variables:", st->rrdfamily->family);
605
- avl_traverse_lock(&st->rrdfamily->variables_root_index, dump_variable);
599
+// ----------------------------------------------------------------------------
600
+// RRDVAR to JSON
601
607
- debug(D_HEALTH, "Available host '%s' variables:", st->rrdhost->hostname);
608
- avl_traverse_lock(&st->rrdhost->variables_root_index, dump_variable);
602
+struct variable2json_helper {
603
+ BUFFER *buf;
604
+ size_t counter;
605
+};
606
610
- return 0;
607
+static void single_variable2json(void *entry, void *data) {
608
+ struct variable2json_helper *helper = (struct variable2json_helper *)data;
609
+ RRDVAR *rv = (RRDVAR *)entry;
610
+ calculated_number value = rrdvar2number(rv);
611
+
612
+ if(unlikely(isnan(value) || isinf(value)))
613
+ buffer_sprintf(helper->buf, "%s\n\t\t\"%s\": null", helper->counter?",":"", rv->name);
614
+ else
615
+ buffer_sprintf(helper->buf, "%s\n\t\t\"%s\": %0.5Lf", helper->counter?",":"", rv->name, (long double)value);
616
+
617
+ helper->counter++;
618
}
619
620
+void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf) {
621
+ struct variable2json_helper helper = {
622
+ .buf = buf,
623
+ .counter = 0
624
+ };
625
+
626
+ 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);
627
+ avl_traverse_lock(&st->variables_root_index, single_variable2json, (void *)&helper);
628
+ buffer_sprintf(buf, "\n\t},\n\t\"family\": \"%s\",\n\t\"family_variables\": {", st->family);
629
+ helper.counter = 0;
630
+ avl_traverse_lock(&st->rrdfamily->variables_root_index, single_variable2json, (void *)&helper);
631
+ buffer_sprintf(buf, "\n\t},\n\t\"host\": \"%s\",\n\t\"host_variables\": {", st->rrdhost->hostname);
632
+ helper.counter = 0;
633
+ avl_traverse_lock(&st->rrdhost->variables_root_index, single_variable2json, (void *)&helper);
634
+ buffer_strcat(buf, "\n\t}\n}\n");
635
+}
636
+
637
+
638
// ----------------------------------------------------------------------------
639
// RRDDIMVAR management
640
// DIMENSION VARIABLES
src/health.h
+2
@@ -350,4 +350,6 @@ extern int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *
350
extern void health_alarms2json(RRDHOST *host, BUFFER *wb, int all);
351
extern void health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after);
352
353
+void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf);
354
+
355
#endif //NETDATA_HEALTH_H
src/rrd.c
+7
-1
@@ -353,6 +353,9 @@ char *rrdset_strncpyz_name(char *to, const char *from, size_t length)
353
354
void rrdset_set_name(RRDSET *st, const char *name)
355
{
356
+ if(unlikely(st->name && !strcmp(st->name, name)))
357
+ return;
358
+
359
debug(D_RRD_CALLS, "rrdset_set_name() old: %s, new: %s", st->name, name);
360
361
char b[CONFIG_MAX_VALUE + 1];
@@ -765,7 +768,10 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
768
769
void rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name)
770
{
768
- debug(D_RRD_CALLS, "rrddim_set_name() %s.%s", st->name, rd->name);
771
+ if(unlikely(rd->name && !strcmp(rd->name, name)))
772
+ return;
773
+
774
+ debug(D_RRD_CALLS, "rrddim_set_name() from %s.%s to %s.%s", st->name, rd->name, st->name, name);
775
776
char varname[CONFIG_MAX_NAME + 1];
777
snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
src/unit_test.c
+10
-4
@@ -975,9 +975,9 @@ int run_test(struct test *test)
975
return errors;
976
}
977
978
-void test_variable_renames(void) {
978
+static int test_variable_renames(void) {
979
fprintf(stderr, "Creating chart\n");
980
- RRDSET *st = rrdset_create("netdata", "CHARTID1", NULL, "netdata", NULL, "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE);
980
+ RRDSET *st = rrdset_create("chart", "ID", NULL, "family", "context", "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE);
981
fprintf(stderr, "Created chart with id '%s', name '%s'\n", st->id, st->name);
982
983
fprintf(stderr, "Creating dimension DIM1\n");
@@ -1011,12 +1011,18 @@ void test_variable_renames(void) {
1011
fprintf(stderr, "Renaming dimension DIM2 to DIM2NAME2\n");
1012
rrddim_set_name(st, rd2, "DIM2NAME2");
1013
fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd2->id, rd2->name);
1014
+
1015
+ BUFFER *buf = buffer_create(1);
1016
+ health_api_v1_chart_variables2json(st, buf);
1017
+ fprintf(stderr, "%s", buffer_tostring(buf));
1018
+ buffer_free(buf);
1019
+ return 1;
1020
}
1021
1022
int run_all_mockup_tests(void)
1023
{
1018
- test_variable_renames();
1019
- exit(1);
1024
+ if(!test_variable_renames())
1025
+ return 1;
1026
1027
if(run_test(&test1))
1028
return 1;
src/web_client.c
+28
-14
@@ -700,17 +700,7 @@ int web_client_api_request_v1_alarm_log(struct web_client *w, char *url)
700
return 200;
701
}
702
703
-int web_client_api_request_v1_charts(struct web_client *w, char *url)
704
-{
705
- (void)url;
706
-
707
- buffer_flush(w->response.data);
708
- w->response.data->contenttype = CT_APPLICATION_JSON;
709
- rrd_stats_api_v1_charts(w->response.data);
710
- return 200;
711
-}
712
-
713
-int web_client_api_request_v1_chart(struct web_client *w, char *url)
703
+int web_client_api_request_single_chart(struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf))
704
{
705
int ret = 400;
706
char *chart = NULL;
@@ -749,13 +739,33 @@ int web_client_api_request_v1_chart(struct web_client *w, char *url)
739
}
740
741
w->response.data->contenttype = CT_APPLICATION_JSON;
752
- rrd_stats_api_v1_chart(st, w->response.data);
742
+ callback(st, w->response.data);
743
return 200;
744
755
-cleanup:
745
+ cleanup:
746
return ret;
747
}
748
749
+int web_client_api_request_v1_alarm_variables(struct web_client *w, char *url)
750
+{
751
+ return web_client_api_request_single_chart(w, url, health_api_v1_chart_variables2json);
752
+}
753
+
754
+int web_client_api_request_v1_charts(struct web_client *w, char *url)
755
+{
756
+ (void)url;
757
+
758
+ buffer_flush(w->response.data);
759
+ w->response.data->contenttype = CT_APPLICATION_JSON;
760
+ rrd_stats_api_v1_charts(w->response.data);
761
+ return 200;
762
+}
763
+
764
+int web_client_api_request_v1_chart(struct web_client *w, char *url)
765
+{
766
+ return web_client_api_request_single_chart(w, url, rrd_stats_api_v1_chart);
767
+}
768
+
769
int web_client_api_request_v1_badge(struct web_client *w, char *url) {
770
int ret = 400;
771
buffer_flush(w->response.data);
@@ -1405,7 +1415,7 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
1415
}
1416
1417
int web_client_api_request_v1(struct web_client *w, char *url) {
1408
- 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;
1418
+ 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;
1419
1420
if(unlikely(hash_data == 0)) {
1421
hash_data = simple_hash("data");
@@ -1415,6 +1425,7 @@ int web_client_api_request_v1(struct web_client *w, char *url) {
1425
hash_badge = simple_hash("badge.svg");
1426
hash_alarms = simple_hash("alarms");
1427
hash_alarm_log = simple_hash("alarm_log");
1428
+ hash_alarm_variables = simple_hash("alarm_variables");
1429
}
1430
1431
// get the command
@@ -1444,6 +1455,9 @@ int web_client_api_request_v1(struct web_client *w, char *url) {
1455
else if(hash == hash_alarm_log && !strcmp(tok, "alarm_log"))
1456
return web_client_api_request_v1_alarm_log(w, url);
1457
1458
+ else if(hash == hash_alarm_variables && !strcmp(tok, "alarm_variables"))
1459
+ return web_client_api_request_v1_alarm_variables(w, url);
1460
+
1461
else {
1462
buffer_flush(w->response.data);
1463
buffer_sprintf(w->response.data, "Unsupported v1 API command: %s", tok);