@cryptotaxi247 / netdata-1 / commits / cd443de78

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

Stelios Fragkakis committed Jan 14, 2021 at 18:50 UTC cd443de780118c46dd8f02530086667d00948373
7 files changed +74 -36
database/rrd.h
+3 -1
@@ -211,6 +211,8 @@ extern int is_valid_label_value(char *value);
211 extern int is_valid_label_key(char *key);
212 extern void free_label_list(struct label *labels);
213 extern struct label *label_list_lookup_key(struct label *head, char *key, uint32_t key_hash);
214 +extern struct label *label_list_lookup_keylist(struct label *head, char *keylist);
215 +extern int label_list_contains_keylist(struct label *head, char *keylist);
216 extern int label_list_contains_key(struct label *head, char *key, uint32_t key_hash);
217 extern int label_list_contains(struct label *head, struct label *check);
218 extern struct label *merge_label_lists(struct label *lo_pri, struct label *hi_pri);
@@ -223,7 +225,7 @@ void reload_host_labels(void);
225 extern void rrdset_add_label_to_new_list(RRDSET *st, char *key, char *value, LABEL_SOURCE source);
226 extern void rrdset_finalize_labels(RRDSET *st);
227 extern void rrdset_update_labels(RRDSET *st, struct label *labels);
226 -extern int rrdset_contains_label_key(RRDSET *st, char *key, uint32_t key_hash);
228 +extern int rrdset_contains_label_keylist(RRDSET *st, char *key);
229 extern struct label *rrdset_lookup_label_key(RRDSET *st, char *key, uint32_t key_hash);
230
231 // ----------------------------------------------------------------------------
database/rrdlabels.c
+22
@@ -159,6 +159,28 @@ int label_list_contains(struct label *head, struct label *check)
159 return label_list_contains_key(head, check->key, check->key_hash);
160 }
161
162 +struct label *label_list_lookup_keylist(struct label *head, char *key)
163 +{
164 + SIMPLE_PATTERN *pattern = NULL;
165 +
166 + pattern = simple_pattern_create(key, ",|\t\r\n\f\v", SIMPLE_PATTERN_EXACT);
167 +
168 + while (head != NULL)
169 + {
170 + if (simple_pattern_matches(pattern, head->key))
171 + break;
172 + head = head->next;
173 + }
174 + simple_pattern_free(pattern);
175 + return head;
176 +}
177 +
178 +int label_list_contains_keylist(struct label *head, char *keylist)
179 +{
180 + return (label_list_lookup_keylist(head, keylist) != NULL);
181 +}
182 +
183 +
184 /* Create a list with entries from both lists.
185 If any entry in the low priority list is masked by an entry in the high priority list then delete it.
186 */
database/rrdset.c
+2 -2
@@ -1949,7 +1949,7 @@ void rrdset_update_labels(RRDSET *st, struct label *labels)
1949 rrdset_finalize_labels(st);
1950 }
1951
1952 -int rrdset_contains_label_key(RRDSET *st, char *key, uint32_t key_hash)
1952 +int rrdset_contains_label_keylist(RRDSET *st, char *keylist)
1953 {
1954 struct label_index *labels = &st->state->labels;
1955 int ret;
@@ -1958,7 +1958,7 @@ int rrdset_contains_label_key(RRDSET *st, char *key, uint32_t key_hash)
1958 return 0;
1959
1960 netdata_rwlock_rdlock(&labels->labels_rwlock);
1961 - ret = label_list_contains_key(labels->head, key, key_hash);
1961 + ret = label_list_contains_keylist(labels->head, keylist);
1962 netdata_rwlock_unlock(&labels->labels_rwlock);
1963
1964 return ret;
libnetdata/simple_pattern/simple_pattern.c
+9
@@ -354,3 +354,12 @@ char *simple_pattern_trim_around_equal(char *src) {
354
355 return store;
356 }
357 +
358 +char *simple_pattern_iterate(SIMPLE_PATTERN **p)
359 +{
360 + struct simple_pattern *root = (struct simple_pattern *) *p;
361 + struct simple_pattern **Proot = (struct simple_pattern **)p;
362 +
363 + (*Proot) = (*Proot)->next;
364 + return (char *) root->match;
365 +}
libnetdata/simple_pattern/simple_pattern.h
+1
@@ -32,6 +32,7 @@ extern void simple_pattern_free(SIMPLE_PATTERN *list);
32
33 extern void simple_pattern_dump(uint64_t debug_type, SIMPLE_PATTERN *p) ;
34 extern int simple_pattern_is_potential_name(SIMPLE_PATTERN *p) ;
35 +extern char *simple_pattern_iterate(SIMPLE_PATTERN **p);
36
37 //Auxiliary function to create a pattern
38 char *simple_pattern_trim_around_equal(char *src);
web/api/formatters/json_wrapper.c
+36 -28
@@ -116,43 +116,51 @@ void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS
116 }
117 buffer_strcat(wb, "],\n");
118 if (chart_label_key) {
119 - uint32_t key_hash = simple_hash(chart_label_key);
120 - struct label *current_label;
119 + buffer_sprintf(wb, " %schart_labels%s: { ", kq, kq);
120
122 - buffer_sprintf(
123 - wb,
124 - " %schart_labels%s: { %s%s%s : [",
125 - kq, kq, kq, chart_label_key, kq);
121 + SIMPLE_PATTERN *pattern = simple_pattern_create(chart_label_key, ",|\t\r\n\f\v", SIMPLE_PATTERN_EXACT);
122 + SIMPLE_PATTERN *original_pattern = pattern;
123 + char *label_key = NULL;
124 + int keys = 0;
125 + while (pattern && (label_key = simple_pattern_iterate(&pattern))) {
126 + uint32_t key_hash = simple_hash(label_key);
127 + struct label *current_label;
128
127 - for (c = 0, i = 0, rd = temp_rd; rd && c < r->d; c++, rd = rd->next) {
128 - if (unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN))
129 - continue;
130 - if (unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO)))
131 - continue;
132 -
133 - if (i)
129 + if (keys)
130 buffer_strcat(wb, ", ");
135 -
136 - current_label = rrdset_lookup_label_key(rd->rrdset, chart_label_key, key_hash);
137 - if (current_label) {
131 + buffer_sprintf(wb, "%s%s%s : [", kq, label_key, kq);
132 + keys++;
133 +
134 + for (c = 0, i = 0, rd = temp_rd; rd && c < r->d; c++, rd = rd->next) {
135 + if (unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN))
136 + continue;
137 + if (unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO)))
138 + continue;
139 + if (i)
140 + buffer_strcat(wb, ", ");
141 +
142 + current_label = rrdset_lookup_label_key(rd->rrdset, label_key, key_hash);
143 + if (current_label) {
144 + buffer_strcat(wb, sq);
145 + buffer_strcat(wb, current_label->value);
146 + buffer_strcat(wb, sq);
147 + } else
148 + buffer_strcat(wb, "null");
149 + i++;
150 + }
151 + if (!i) {
152 + rows = 0;
153 buffer_strcat(wb, sq);
139 - buffer_strcat(wb, current_label->value);
154 + buffer_strcat(wb, "no data");
155 buffer_strcat(wb, sq);
141 - } else
142 - buffer_strcat(wb, "null");
143 - i++;
156 + }
157 + buffer_strcat(wb, "]");
158 }
145 - if (!i) {
146 - rows = 0;
147 - buffer_strcat(wb, sq);
148 - buffer_strcat(wb, "no data");
149 - buffer_strcat(wb, sq);
150 - }
151 - buffer_strcat(wb, "] },\n");
159 + buffer_strcat(wb, "},\n");
160 + simple_pattern_free(original_pattern);
161 }
162 }
163
155 -
164 buffer_sprintf(wb, " %slatest_values%s: ["
165 , kq, kq);
166
web/api/web_api_v1.c
+1 -5
@@ -501,15 +501,11 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
501 if (context && !chart) {
502 RRDSET *st1;
503 uint32_t context_hash = simple_hash(context);
504 - uint32_t key_hash;
505 -
506 - if (chart_label_key)
507 - key_hash = simple_hash(chart_label_key);
504
505 rrdhost_rdlock(host);
506 rrdset_foreach_read(st1, host) {
507 if (st1->hash_context == context_hash && !strcmp(st1->context, context) &&
512 - (!chart_label_key || rrdset_contains_label_key(st1, chart_label_key, key_hash)))
508 + (!chart_label_key || rrdset_contains_label_keylist(st1, chart_label_key)))
509 build_context_param_list(&context_param_list, st1);
510 }
511 rrdhost_unlock(host);