Browse Source

Support multiple chart label keys in data queries (#10483)

Stelios Fragkakis 4 years ago
parent
commit
cd443de780

+ 3 - 1
database/rrd.h

@@ -211,6 +211,8 @@ extern int is_valid_label_value(char *value);
 extern int is_valid_label_key(char *key);
 extern int is_valid_label_key(char *key);
 extern void free_label_list(struct label *labels);
 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_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_key(struct label *head, char *key, uint32_t key_hash);
 extern int label_list_contains(struct label *head, struct label *check);
 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);
 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_add_label_to_new_list(RRDSET *st, char *key, char *value, LABEL_SOURCE source);
 extern void rrdset_finalize_labels(RRDSET *st);
 extern void rrdset_finalize_labels(RRDSET *st);
 extern void rrdset_update_labels(RRDSET *st, struct label *labels);
 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);
 extern struct label *rrdset_lookup_label_key(RRDSET *st, char *key, uint32_t key_hash);
 
 
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------

+ 22 - 0
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);
     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.
 /* 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.
    If any entry in the low priority list is masked by an entry in the high priority list then delete it.
 */
 */

+ 2 - 2
database/rrdset.c

@@ -1949,7 +1949,7 @@ void rrdset_update_labels(RRDSET *st, struct label *labels)
     rrdset_finalize_labels(st);
     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;
     struct label_index *labels = &st->state->labels;
     int ret;
     int ret;
@@ -1958,7 +1958,7 @@ int rrdset_contains_label_key(RRDSET *st, char *key, uint32_t key_hash)
         return 0;
         return 0;
 
 
     netdata_rwlock_rdlock(&labels->labels_rwlock);
     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);
     netdata_rwlock_unlock(&labels->labels_rwlock);
 
 
     return ret;
     return ret;

+ 9 - 0
libnetdata/simple_pattern/simple_pattern.c

@@ -354,3 +354,12 @@ char *simple_pattern_trim_around_equal(char *src) {
 
 
     return store;
     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;
+}

+ 1 - 0
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 void simple_pattern_dump(uint64_t debug_type, SIMPLE_PATTERN *p) ;
 extern int simple_pattern_is_potential_name(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
 //Auxiliary function to create a pattern
 char *simple_pattern_trim_around_equal(char *src);
 char *simple_pattern_trim_around_equal(char *src);

+ 36 - 28
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");
         buffer_strcat(wb, "],\n");
         if (chart_label_key) {
         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, ", ");
                     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, sq);
-                    buffer_strcat(wb, current_label->value);
+                    buffer_strcat(wb, "no data");
                     buffer_strcat(wb, sq);
                     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: ["
     buffer_sprintf(wb, "   %slatest_values%s: ["
                    , kq, kq);
                    , kq, kq);
 
 

+ 1 - 5
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) {
     if (context && !chart) {
         RRDSET *st1;
         RRDSET *st1;
         uint32_t context_hash = simple_hash(context);
         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);
         rrdhost_rdlock(host);
         rrdset_foreach_read(st1, host) {
         rrdset_foreach_read(st1, host) {
             if (st1->hash_context == context_hash && !strcmp(st1->context, context) &&
             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);
                 build_context_param_list(&context_param_list, st1);
         }
         }
         rrdhost_unlock(host);
         rrdhost_unlock(host);