Change query label matching logic (#16827)
* Match multi labels * Rework, add support for weights * Fix function return value * Cleanup function
Stelios Fragkakis committed
Jan 23, 2024 at 20:32 UTC
952631b952bd693ac134a22682d99226a6123260
2 files changed
+122
-7
database/contexts/query_target.c
+114
-7
@@ -11,6 +11,7 @@ static void query_dimension_release(QUERY_DIMENSION *qd);
11
static void query_instance_release(QUERY_INSTANCE *qi);
12
static void query_context_release(QUERY_CONTEXT *qc);
13
static void query_node_release(QUERY_NODE *qn);
14
+static void free_label_pattern_list(struct label_pattern_list *lpl);
15
16
static __thread QUERY_TARGET *thread_qt = NULL;
17
static struct {
@@ -83,6 +84,9 @@ void query_target_release(QUERY_TARGET *qt) {
84
simple_pattern_free(qt->instances.labels_pattern);
85
qt->instances.labels_pattern = NULL;
86
87
+ free_label_pattern_list(qt->instances.label_pattern_list);
88
+ qt->instances.label_pattern_list = NULL;
89
+
90
simple_pattern_free(qt->query.pattern);
91
qt->query.pattern = NULL;
92
@@ -725,11 +729,25 @@ static inline SIMPLE_PATTERN_RESULT query_instance_matches(QUERY_INSTANCE *qi,
729
return ret;
730
}
731
728
-static inline bool query_instance_matches_labels(RRDINSTANCE *ri, SIMPLE_PATTERN *chart_label_key_sp, SIMPLE_PATTERN *labels_sp) {
729
- if ((chart_label_key_sp && !rrdlabels_match_simple_pattern_parsed(
730
- ri->rrdlabels, chart_label_key_sp, '\0', NULL)) ||
731
- (labels_sp && !rrdlabels_match_simple_pattern_parsed(
732
- ri->rrdlabels, labels_sp, ':', NULL)))
732
+static inline bool query_instance_matches_labels(
733
+ RRDINSTANCE *ri,
734
+ SIMPLE_PATTERN *chart_label_key_sp,
735
+ SIMPLE_PATTERN *labels_sp,
736
+ struct label_pattern_list *lpl)
737
+{
738
+
739
+ if (chart_label_key_sp && !rrdlabels_match_simple_pattern_parsed(ri->rrdlabels, chart_label_key_sp, '\0', NULL))
740
+ return false;
741
+
742
+ if (lpl) {
743
+ for (size_t i = 0; i < lpl->size; i++) {
744
+ if (!rrdlabels_match_simple_pattern_parsed(ri->rrdlabels, lpl->labels_pattern[i], ':', NULL))
745
+ return false;
746
+ }
747
+ return true;
748
+ }
749
+
750
+ if (labels_sp && !rrdlabels_match_simple_pattern_parsed(ri->rrdlabels, labels_sp, ':', NULL))
751
return false;
752
753
return true;
@@ -752,7 +770,11 @@ static bool query_instance_add(QUERY_TARGET_LOCALS *qtl, QUERY_NODE *qn, QUERY_C
770
qi, ri, qt->instances.pattern, qtl->match_ids, qtl->match_names, qt->request.version, qtl->host_node_id_str));
771
772
if(queryable_instance)
755
- queryable_instance = query_instance_matches_labels(ri, qt->instances.chart_label_key_pattern, qt->instances.labels_pattern);
773
+ queryable_instance = query_instance_matches_labels(
774
+ ri,
775
+ qt->instances.chart_label_key_pattern,
776
+ qt->instances.labels_pattern,
777
+ qt->instances.label_pattern_list);
778
779
if(queryable_instance) {
780
if(qt->instances.alerts_pattern && !query_target_match_alert_pattern(ria, qt->instances.alerts_pattern))
@@ -1021,6 +1043,82 @@ void query_target_generate_name(QUERY_TARGET *qt) {
1043
json_fix_string(qt->id);
1044
}
1045
1046
+static void add_label_pattern(struct label_pattern_list *lpl, char *label_key_value)
1047
+{
1048
+ char *label_key;
1049
+
1050
+ if (unlikely(!label_key_value || !(label_key = strchr(label_key_value, ':'))))
1051
+ return;
1052
+
1053
+ *label_key = '\0';
1054
+ STRING *key_match = string_strdupz(label_key_value);
1055
+ *label_key = ':';
1056
+
1057
+ size_t index;
1058
+ bool need_to_add = true;
1059
+
1060
+ for (size_t i = 0; i < lpl->size; i++) {
1061
+ if (lpl->key[i] == key_match) {
1062
+ index = i;
1063
+ need_to_add = false;
1064
+ break;
1065
+ }
1066
+ }
1067
+
1068
+ if (need_to_add) {
1069
+ index = lpl->size++;
1070
+ lpl->buffer_list = reallocz(lpl->buffer_list, lpl->size * sizeof(BUFFER *));
1071
+ lpl->key = reallocz(lpl->key, lpl->size * sizeof(STRING *));
1072
+
1073
+ lpl->buffer_list[index] = buffer_create(128, NULL);
1074
+ lpl->key[index] = key_match;
1075
+ } else
1076
+ buffer_strncat(lpl->buffer_list[index], ",", 1);
1077
+
1078
+ buffer_strcat(lpl->buffer_list[index], label_key_value);
1079
+}
1080
+
1081
+static struct label_pattern_list *build_pattern_list(SIMPLE_PATTERN *pattern)
1082
+{
1083
+ if (unlikely(!pattern))
1084
+ return NULL;
1085
+
1086
+ char *label_key = NULL;
1087
+
1088
+ struct label_pattern_list *lpl = callocz(1, sizeof(*lpl));
1089
+
1090
+ while (pattern && (label_key = simple_pattern_iterate(&pattern)))
1091
+ add_label_pattern(lpl, label_key);
1092
+
1093
+ lpl->labels_pattern = callocz(lpl->size, sizeof(SIMPLE_PATTERN *));
1094
+
1095
+ for (size_t i = 0; i < lpl->size; i++) {
1096
+ lpl->labels_pattern[i] = string_to_simple_pattern(buffer_tostring(lpl->buffer_list[i]));
1097
+ buffer_free(lpl->buffer_list[i]);
1098
+ string_freez(lpl->key[i]);
1099
+ }
1100
+
1101
+ freez(lpl->buffer_list);
1102
+ lpl->buffer_list = NULL;
1103
+
1104
+ freez(lpl->key);
1105
+ lpl->key = NULL;
1106
+ return lpl;
1107
+}
1108
+
1109
+static void free_label_pattern_list(struct label_pattern_list *lpl)
1110
+{
1111
+ if (unlikely(!lpl))
1112
+ return;
1113
+
1114
+ for(size_t i = 0; i < lpl->size; i++)
1115
+ simple_pattern_free(lpl->labels_pattern[i]);
1116
+
1117
+ freez(lpl->labels_pattern);
1118
+ freez(lpl);
1119
+}
1120
+
1121
+
1122
QUERY_TARGET *query_target_create(QUERY_TARGET_REQUEST *qtr) {
1123
if(!service_running(ABILITY_DATA_QUERIES))
1124
return NULL;
@@ -1085,6 +1183,10 @@ QUERY_TARGET *query_target_create(QUERY_TARGET_REQUEST *qtr) {
1183
qt->query.pattern = string_to_simple_pattern(qtl.dimensions);
1184
qt->instances.chart_label_key_pattern = string_to_simple_pattern(qtl.chart_label_key);
1185
qt->instances.labels_pattern = string_to_simple_pattern(qtl.labels);
1186
+
1187
+ if (qt->instances.labels_pattern)
1188
+ qt->instances.label_pattern_list = build_pattern_list(qt->instances.labels_pattern);
1189
+
1190
qt->instances.alerts_pattern = string_to_simple_pattern(qtl.alerts);
1191
1192
qtl.match_ids = qt->request.options & RRDR_OPTION_MATCH_IDS;
@@ -1156,6 +1258,11 @@ ssize_t weights_foreach_rrdmetric_in_context(RRDCONTEXT_ACQUIRED *rca,
1258
1259
ssize_t count = 0;
1260
RRDINSTANCE *ri;
1261
+
1262
+ struct label_pattern_list *lpl = NULL;
1263
+ if (labels_sp)
1264
+ lpl = build_pattern_list(labels_sp);
1265
+
1266
dfe_start_read(rc->rrdinstances, ri) {
1267
if(rrd_flag_is_deleted(ri))
1268
continue;
@@ -1172,7 +1279,7 @@ ssize_t weights_foreach_rrdmetric_in_context(RRDCONTEXT_ACQUIRED *rca,
1279
continue;
1280
}
1281
1175
- if(!query_instance_matches_labels(ri, chart_label_key_sp, labels_sp))
1282
+ if(!query_instance_matches_labels(ri, chart_label_key_sp, labels_sp, lpl))
1283
continue;
1284
1285
if(alerts_sp && !query_target_match_alert_pattern(ria, alerts_sp))
database/contexts/rrdcontext.h
+8
@@ -329,6 +329,13 @@ struct query_timings {
329
usec_t finished_ut;
330
};
331
332
+struct label_pattern_list {
333
+ BUFFER **buffer_list;
334
+ STRING **key;
335
+ SIMPLE_PATTERN **labels_pattern;
336
+ size_t size;
337
+};
338
+
339
#define query_view_update_every(qt) ((qt)->window.group * (qt)->window.query_granularity)
340
341
typedef struct query_target {
@@ -379,6 +386,7 @@ typedef struct query_target {
386
uint32_t size; // the size of the array
387
SIMPLE_PATTERN *pattern;
388
SIMPLE_PATTERN *labels_pattern;
389
+ struct label_pattern_list *label_pattern_list;
390
SIMPLE_PATTERN *alerts_pattern;
391
SIMPLE_PATTERN *chart_label_key_pattern;
392
} instances;