From: Aki Tuomi Date: Tue, 31 Jan 2023 11:43:50 +0000 (+0200) Subject: stats: Add support for discrete modifiers X-Git-Tag: 2.4.0~2917 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7c54e88d7eda5515776e29af2b419e16ebccedef;p=thirdparty%2Fdovecot%2Fcore.git stats: Add support for discrete modifiers --- diff --git a/src/stats/stats-metrics.c b/src/stats/stats-metrics.c index 5c92a31783..dc11956d9a 100644 --- a/src/stats/stats-metrics.c +++ b/src/stats/stats-metrics.c @@ -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: diff --git a/src/stats/stats-settings.c b/src/stats/stats-settings.c index 78402d0780..a05aaa3146 100644 --- a/src/stats/stats-settings.c +++ b/src/stats/stats-settings.c @@ -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) { /* :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, ¶ms[2], error_r)) return FALSE; - } } else if (strcmp(params[1], "exponential") == 0) { /* :exponential::: */ if (!parse_metric_group_by_exp(pool, &group_by, ¶ms[2], error_r)) diff --git a/src/stats/stats-settings.h b/src/stats/stats-settings.h index 54b7f9e4d6..a2fec1bd8c 100644 --- a/src/stats/stats-settings.h +++ b/src/stats/stats-settings.h @@ -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; };