diff options
author | Stelios Fragkakis <52996999+stelfrag@users.noreply.github.com> | 2021-01-14 18:50:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-14 18:50:33 +0200 |
commit | cd443de780118c46dd8f02530086667d00948373 (patch) | |
tree | e29f21e28eb9eeb1d11539216a9e623ac225d3de | |
parent | de6035c543296de179e359a415664106d66c3878 (diff) |
Support multiple chart label keys in data queries (#10483)
-rw-r--r-- | database/rrd.h | 4 | ||||
-rw-r--r-- | database/rrdlabels.c | 22 | ||||
-rw-r--r-- | database/rrdset.c | 4 | ||||
-rw-r--r-- | libnetdata/simple_pattern/simple_pattern.c | 9 | ||||
-rw-r--r-- | libnetdata/simple_pattern/simple_pattern.h | 1 | ||||
-rw-r--r-- | web/api/formatters/json_wrapper.c | 64 | ||||
-rw-r--r-- | web/api/web_api_v1.c | 6 |
7 files changed, 74 insertions, 36 deletions
diff --git a/database/rrd.h b/database/rrd.h index 20891409d4..86f4226348 100644 --- a/database/rrd.h +++ b/database/rrd.h @@ -211,6 +211,8 @@ extern int is_valid_label_value(char *value); extern int is_valid_label_key(char *key); extern void free_label_list(struct label *labels); extern struct label *label_list_lookup_key(struct label *head, char *key, uint32_t key_hash); +extern struct label *label_list_lookup_keylist(struct label *head, char *keylist); +extern int label_list_contains_keylist(struct label *head, char *keylist); extern int label_list_contains_key(struct label *head, char *key, uint32_t key_hash); extern int label_list_contains(struct label *head, struct label *check); extern struct label *merge_label_lists(struct label *lo_pri, struct label *hi_pri); @@ -223,7 +225,7 @@ void reload_host_labels(void); extern void rrdset_add_label_to_new_list(RRDSET *st, char *key, char *value, LABEL_SOURCE source); extern void rrdset_finalize_labels(RRDSET *st); extern void rrdset_update_labels(RRDSET *st, struct label *labels); -extern int rrdset_contains_label_key(RRDSET *st, char *key, uint32_t key_hash); +extern int rrdset_contains_label_keylist(RRDSET *st, char *key); extern struct label *rrdset_lookup_label_key(RRDSET *st, char *key, uint32_t key_hash); // ---------------------------------------------------------------------------- diff --git a/database/rrdlabels.c b/database/rrdlabels.c index b423f422a4..f9583769d5 100644 --- a/database/rrdlabels.c +++ b/database/rrdlabels.c @@ -159,6 +159,28 @@ int label_list_contains(struct label *head, struct label *check) return label_list_contains_key(head, check->key, check->key_hash); } +struct label *label_list_lookup_keylist(struct label *head, char *key) +{ + SIMPLE_PATTERN *pattern = NULL; + + pattern = simple_pattern_create(key, ",|\t\r\n\f\v", SIMPLE_PATTERN_EXACT); + + while (head != NULL) + { + if (simple_pattern_matches(pattern, head->key)) + break; + head = head->next; + } + simple_pattern_free(pattern); + return head; +} + +int label_list_contains_keylist(struct label *head, char *keylist) +{ + return (label_list_lookup_keylist(head, keylist) != NULL); +} + + /* Create a list with entries from both lists. If any entry in the low priority list is masked by an entry in the high priority list then delete it. */ diff --git a/database/rrdset.c b/database/rrdset.c index 163fbb0715..760f401184 100644 --- a/database/rrdset.c +++ b/database/rrdset.c @@ -1949,7 +1949,7 @@ void rrdset_update_labels(RRDSET *st, struct label *labels) rrdset_finalize_labels(st); } -int rrdset_contains_label_key(RRDSET *st, char *key, uint32_t key_hash) +int rrdset_contains_label_keylist(RRDSET *st, char *keylist) { struct label_index *labels = &st->state->labels; int ret; @@ -1958,7 +1958,7 @@ int rrdset_contains_label_key(RRDSET *st, char *key, uint32_t key_hash) return 0; netdata_rwlock_rdlock(&labels->labels_rwlock); - ret = label_list_contains_key(labels->head, key, key_hash); + ret = label_list_contains_keylist(labels->head, keylist); netdata_rwlock_unlock(&labels->labels_rwlock); return ret; diff --git a/libnetdata/simple_pattern/simple_pattern.c b/libnetdata/simple_pattern/simple_pattern.c index 44fa42a629..70b06a22bc 100644 --- a/libnetdata/simple_pattern/simple_pattern.c +++ b/libnetdata/simple_pattern/simple_pattern.c @@ -354,3 +354,12 @@ char *simple_pattern_trim_around_equal(char *src) { return store; } + +char *simple_pattern_iterate(SIMPLE_PATTERN **p) +{ + struct simple_pattern *root = (struct simple_pattern *) *p; + struct simple_pattern **Proot = (struct simple_pattern **)p; + + (*Proot) = (*Proot)->next; + return (char *) root->match; +} diff --git a/libnetdata/simple_pattern/simple_pattern.h b/libnetdata/simple_pattern/simple_pattern.h index ec6b535879..36fbbde7df 100644 --- a/libnetdata/simple_pattern/simple_pattern.h +++ b/libnetdata/simple_pattern/simple_pattern.h @@ -32,6 +32,7 @@ extern void simple_pattern_free(SIMPLE_PATTERN *list); extern void simple_pattern_dump(uint64_t debug_type, SIMPLE_PATTERN *p) ; extern int simple_pattern_is_potential_name(SIMPLE_PATTERN *p) ; +extern char *simple_pattern_iterate(SIMPLE_PATTERN **p); //Auxiliary function to create a pattern char *simple_pattern_trim_around_equal(char *src); diff --git a/web/api/formatters/json_wrapper.c b/web/api/formatters/json_wrapper.c index 72967375d7..cf4f1099a2 100644 --- a/web/api/formatters/json_wrapper.c +++ b/web/api/formatters/json_wrapper.c @@ -116,43 +116,51 @@ void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS } buffer_strcat(wb, "],\n"); if (chart_label_key) { - uint32_t key_hash = simple_hash(chart_label_key); - struct label *current_label; + buffer_sprintf(wb, " %schart_labels%s: { ", kq, kq); - buffer_sprintf( - wb, - " %schart_labels%s: { %s%s%s : [", - kq, kq, kq, chart_label_key, kq); + SIMPLE_PATTERN *pattern = simple_pattern_create(chart_label_key, ",|\t\r\n\f\v", SIMPLE_PATTERN_EXACT); + SIMPLE_PATTERN *original_pattern = pattern; + char *label_key = NULL; + int keys = 0; + while (pattern && (label_key = simple_pattern_iterate(&pattern))) { + uint32_t key_hash = simple_hash(label_key); + struct label *current_label; - for (c = 0, i = 0, rd = temp_rd; rd && c < r->d; c++, rd = rd->next) { - if (unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) - continue; - if (unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) - continue; - - if (i) + if (keys) buffer_strcat(wb, ", "); - - current_label = rrdset_lookup_label_key(rd->rrdset, chart_label_key, key_hash); - if (current_label) { + buffer_sprintf(wb, "%s%s%s : [", kq, label_key, kq); + keys++; + + for (c = 0, i = 0, rd = temp_rd; rd && c < r->d; c++, rd = rd->next) { + if (unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) + continue; + if (unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) + continue; + if (i) + buffer_strcat(wb, ", "); + + current_label = rrdset_lookup_label_key(rd->rrdset, label_key, key_hash); + if (current_label) { + buffer_strcat(wb, sq); + buffer_strcat(wb, current_label->value); + buffer_strcat(wb, sq); + } else + buffer_strcat(wb, "null"); + i++; + } + if (!i) { + rows = 0; buffer_strcat(wb, sq); - buffer_strcat(wb, current_label->value); + buffer_strcat(wb, "no data"); buffer_strcat(wb, sq); - } else - buffer_strcat(wb, "null"); - i++; + } + buffer_strcat(wb, "]"); } - if (!i) { - rows = 0; - buffer_strcat(wb, sq); - buffer_strcat(wb, "no data"); - buffer_strcat(wb, sq); - } - buffer_strcat(wb, "] },\n"); + buffer_strcat(wb, "},\n"); + simple_pattern_free(original_pattern); } } - buffer_sprintf(wb, " %slatest_values%s: [" , kq, kq); diff --git a/web/api/web_api_v1.c b/web/api/web_api_v1.c index cbfeee9a5c..4287675418 100644 --- a/web/api/web_api_v1.c +++ b/web/api/web_api_v1.c @@ -501,15 +501,11 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c if (context && !chart) { RRDSET *st1; uint32_t context_hash = simple_hash(context); - uint32_t key_hash; - - if (chart_label_key) - key_hash = simple_hash(chart_label_key); rrdhost_rdlock(host); rrdset_foreach_read(st1, host) { if (st1->hash_context == context_hash && !strcmp(st1->context, context) && - (!chart_label_key || rrdset_contains_label_key(st1, chart_label_key, key_hash))) + (!chart_label_key || rrdset_contains_label_keylist(st1, chart_label_key))) build_context_param_list(&context_param_list, st1); } rrdhost_unlock(host); |