@cryptotaxi247 / netdata-1 / commits / 952631b95

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;