]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
stats: Support group_by for string lists
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 19 Mar 2021 11:13:45 +0000 (13:13 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Wed, 29 Sep 2021 10:09:58 +0000 (10:09 +0000)
src/stats/stats-metrics.c

index 46283b06cfa5c73c6f8a0f2f5cdfad69b8d8b46a..3529262bf206c1bdb39df645f5c5a7a32d1c6ca9 100644 (file)
@@ -525,6 +525,23 @@ stats_metric_group_by_field(struct metric *metric, struct event *event,
        stats_metric_event(sub_metric, event, pool);
 }
 
+static void
+stats_event_get_strlist(struct event *event, const char *name,
+                       ARRAY_TYPE(const_string) *strings)
+{
+       if (event == NULL)
+               return;
+
+       const struct event_field *field =
+               event_find_field_nonrecursive(event, name);
+       if (field != NULL) {
+               const char *str;
+               array_foreach_elem(&field->value.strlist, str)
+                       array_push_back(strings, &str);
+       }
+       stats_event_get_strlist(event_get_parent(event), name, strings);
+}
+
 static void
 stats_metric_group_by(struct metric *metric, struct event *event, pool_t pool)
 {
@@ -535,7 +552,36 @@ stats_metric_group_by(struct metric *metric, struct event *event, pool_t pool)
        if (field == NULL)
                return;
 
-       stats_metric_group_by_field(metric, event, field, pool);
+       if (field->value_type != EVENT_FIELD_VALUE_TYPE_STRLIST)
+               stats_metric_group_by_field(metric, event, field, pool);
+       else {
+               /* Handle each string in strlist separately. The strlist needs
+                  to be combined from the event and its parents, as well as
+                  the global event and its parents. */
+               ARRAY_TYPE(const_string) strings;
+
+               t_array_init(&strings, 8);
+               stats_event_get_strlist(event, metric->group_by[0].field,
+                                       &strings);
+               stats_event_get_strlist(event_get_global(),
+                                       metric->group_by[0].field, &strings);
+
+               struct event_field str_field = {
+                       .value_type = EVENT_FIELD_VALUE_TYPE_STR,
+               };
+               const char *str;
+
+               /* sort strings so duplicates can be easily skipped */
+               array_sort(&strings, i_strcmp_p);
+               array_foreach_elem(&strings, str) {
+                       if (str_field.value.str == NULL ||
+                           strcmp(str_field.value.str, str) != 0) {
+                               str_field.value.str = str;
+                               stats_metric_group_by_field(metric, event,
+                                                           &str_field, pool);
+                       }
+               }
+       }
 }
 
 static void