]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
stats: Add support for discrete modifiers
authorAki Tuomi <aki.tuomi@open-xchange.com>
Tue, 31 Jan 2023 11:43:50 +0000 (13:43 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Thu, 16 Mar 2023 05:38:57 +0000 (07:38 +0200)
src/stats/stats-metrics.c
src/stats/stats-settings.c
src/stats/stats-settings.h

index 5c92a317837b72fd6684cd146bc1c028c5df27fa..dc11956d9a4bd40b135a1e108ef3b5d959f7240a 100644 (file)
@@ -496,6 +496,25 @@ stats_metric_group_by_get_label(const struct event_field *field,
        i_panic("unknown group-by function %d", group_by->func);
 }
 
+/* Handle string modifiers */
+static inline const char *
+label_by_mod_str(const struct stats_metric_settings_group_by *group_by,
+                const char *value)
+{
+       if ((group_by->mod & STATS_METRICS_GROUPBY_DOMAIN) != 0) {
+               const char *domain = strrchr(value, '@');
+               if (domain != NULL)
+                       value = domain+1;
+               else
+                       value = "";
+       }
+       if ((group_by->mod & STATS_METRICS_GROUPBY_UPPERCASE) != 0)
+               value = t_str_ucase(value);
+       if ((group_by->mod & STATS_METRICS_GROUPBY_LOWERCASE) != 0)
+               value = t_str_lcase(value);
+       return value;
+}
+
 static const char *
 stats_metric_group_by_value_label(const struct event_field *field,
                                  const struct stats_metric_settings_group_by *group_by,
@@ -503,7 +522,7 @@ stats_metric_group_by_value_label(const struct event_field *field,
 {
        switch (value->type) {
        case METRIC_VALUE_TYPE_STR:
-               return field->value.str;
+               return label_by_mod_str(group_by, field->value.str);
        case METRIC_VALUE_TYPE_INT:
                return dec2str(field->value.intmax);
        case METRIC_VALUE_TYPE_IP:
index 78402d078092a99b7825650cf012727a29994d88..a05aaa314659c80f26e66830a97c1ef8ec6715cc 100644 (file)
@@ -440,6 +440,27 @@ static bool parse_metric_group_by_lin(pool_t pool, struct stats_metric_settings_
        return TRUE;
 }
 
+static bool
+parse_metric_group_by_mod(pool_t pool ATTR_UNUSED,
+                         struct stats_metric_settings_group_by *group_by,
+                         const char *const *params, const char **error_r)
+{
+       for (; *params != NULL; params++) {
+               if (strcmp(*params, "domain") == 0)
+                       group_by->mod |= STATS_METRICS_GROUPBY_DOMAIN;
+               else if (strcmp(*params, "uppercase") == 0)
+                       group_by->mod |= STATS_METRICS_GROUPBY_UPPERCASE;
+               else if (strcmp(*params, "lowercase") == 0)
+                       group_by->mod |= STATS_METRICS_GROUPBY_LOWERCASE;
+               else {
+                       *error_r = t_strdup_printf("Unknown modifier '%s' for '%s'",
+                                                  *params, group_by->field);
+                       return FALSE;
+               }
+       }
+       return TRUE;
+}
+
 static bool parse_metric_group_by(struct stats_metric_settings *set,
                                  pool_t pool, const char **error_r)
 {
@@ -467,11 +488,8 @@ static bool parse_metric_group_by(struct stats_metric_settings *set,
                } else if (strcmp(params[1], "discrete") == 0) {
                        /* <field>:discrete */
                        group_by.func = STATS_METRIC_GROUPBY_DISCRETE;
-                       if (params[2] != NULL) {
-                               *error_r = "group_by 'discrete' aggregate function "
-                                          "does not take any args";
+                       if (!parse_metric_group_by_mod(pool, &group_by, &params[2], error_r))
                                return FALSE;
-                       }
                } else if (strcmp(params[1], "exponential") == 0) {
                        /* <field>:exponential:<min mag>:<max mag>:<base> */
                        if (!parse_metric_group_by_exp(pool, &group_by, &params[2], error_r))
index 54b7f9e4d60613a59d213c5611e25b0b57b8fa8a..a2fec1bd8c69674bec8b641021edca2c602dae90 100644 (file)
@@ -78,6 +78,16 @@ enum stats_metric_group_by_func {
        STATS_METRIC_GROUPBY_QUANTIZED,
 };
 
+/* A modifier for discrete group by.
+ *
+ * Implemented as bit field, as we allow multiple modifiers.
+ */
+enum stats_metric_group_by_modifier {
+       /* extract domain from user@domain */
+       STATS_METRICS_GROUPBY_DOMAIN     = BIT(0),
+       STATS_METRICS_GROUPBY_UPPERCASE  = BIT(1),
+       STATS_METRICS_GROUPBY_LOWERCASE  = BIT(2),
+};
 /*
  * A range covering a stats bucket.  The the interval is half closed - the
  * minimum is excluded and the maximum is included.  In other words: (min, max].
@@ -92,6 +102,7 @@ struct stats_metric_settings_bucket_range {
 struct stats_metric_settings_group_by {
        const char *field;
        enum stats_metric_group_by_func func;
+       enum stats_metric_group_by_modifier mod;
        unsigned int num_ranges;
        struct stats_metric_settings_bucket_range *ranges;
 };