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);