bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen#include "lib.h"
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen#include "array.h"
5f08b0309190ec818d46bfe0e497468b30714a93Timo Sirainen#include "stats-dist.h"
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen#include "time-util.h"
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen#include "event-filter.h"
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen#include "stats-settings.h"
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen#include "stats-metrics.h"
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstruct stats_metrics {
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen pool_t pool;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct event_filter *filter;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen ARRAY(struct metric *) metrics;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen};
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstatic void
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstats_metric_settings_to_query(const struct stats_metric_settings *set,
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct event_filter_query *query_r)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen{
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen i_zero(query_r);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen /* generate fields for event filter */
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen if (array_is_created(&set->filter)) {
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct event_filter_field *filter_fields;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen const char *const *filters;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen unsigned int i, count;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen filters = array_get(&set->filter, &count);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen i_assert(count % 2 == 0);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen count /= 2;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen filter_fields = t_new(struct event_filter_field, count + 1);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen for (i = 0; i < count; i++) {
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen filter_fields[i].key = filters[i*2];
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen filter_fields[i].value = filters[i*2+1];
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen }
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen query_r->fields = filter_fields;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen }
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen /* add query to the event filter */
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen query_r->categories = t_strsplit_spaces(set->categories, " ");
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen query_r->name = set->event_name;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen query_r->source_filename = t_strcut(set->source_location, ':');
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen query_r->source_linenum = set->parsed_source_linenum;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen}
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstatic void stats_metrics_add_set(struct stats_metrics *metrics,
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen const struct stats_metric_settings *set)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen{
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct event_filter_query query;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct metric *metric;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen const char *const *fields;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen metric = p_new(metrics->pool, struct metric, 1);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen metric->name = p_strdup(metrics->pool, set->name);
5f08b0309190ec818d46bfe0e497468b30714a93Timo Sirainen metric->duration_stats = stats_dist_init();
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen fields = t_strsplit_spaces(set->fields, " ");
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen metric->fields_count = str_array_length(fields);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen if (metric->fields_count > 0) {
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen metric->fields = p_new(metrics->pool, struct metric_field,
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen metric->fields_count);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen for (unsigned int i = 0; i < metric->fields_count; i++) {
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen metric->fields[i].field_key =
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen p_strdup(metrics->pool, fields[i]);
5f08b0309190ec818d46bfe0e497468b30714a93Timo Sirainen metric->fields[i].stats = stats_dist_init();
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen }
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen }
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen array_append(&metrics->metrics, &metric, 1);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen stats_metric_settings_to_query(set, &query);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen query.context = metric;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen event_filter_add(metrics->filter, &query);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen}
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstatic void
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstats_metrics_add_from_settings(struct stats_metrics *metrics,
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen const struct stats_settings *set)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen{
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct stats_metric_settings *const *metric_setp;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen if (!array_is_created(&set->metrics)) {
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen p_array_init(&metrics->metrics, metrics->pool, 0);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen return;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen }
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen p_array_init(&metrics->metrics, metrics->pool,
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen array_count(&set->metrics));
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen array_foreach(&set->metrics, metric_setp) T_BEGIN {
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen stats_metrics_add_set(metrics, *metric_setp);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen } T_END;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen}
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstruct stats_metrics *stats_metrics_init(const struct stats_settings *set)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen{
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct stats_metrics *metrics;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen pool_t pool = pool_alloconly_create("stats metrics", 1024);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen metrics = p_new(pool, struct stats_metrics, 1);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen metrics->pool = pool;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen metrics->filter = event_filter_create();
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen stats_metrics_add_from_settings(metrics, set);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen return metrics;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen}
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstatic void stats_metric_free(struct metric *metric)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen{
5f08b0309190ec818d46bfe0e497468b30714a93Timo Sirainen stats_dist_deinit(&metric->duration_stats);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen for (unsigned int i = 0; i < metric->fields_count; i++)
5f08b0309190ec818d46bfe0e497468b30714a93Timo Sirainen stats_dist_deinit(&metric->fields[i].stats);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen}
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenvoid stats_metrics_deinit(struct stats_metrics **_metrics)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen{
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct stats_metrics *metrics = *_metrics;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct metric *const *metricp;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen *_metrics = NULL;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen array_foreach(&metrics->metrics, metricp)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen stats_metric_free(*metricp);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen event_filter_unref(&metrics->filter);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen pool_unref(&metrics->pool);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen}
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
9c675f5e259c19f9fdc40808439479131b32421eTimo Sirainenvoid stats_metrics_reset(struct stats_metrics *metrics)
9c675f5e259c19f9fdc40808439479131b32421eTimo Sirainen{
9c675f5e259c19f9fdc40808439479131b32421eTimo Sirainen struct metric *const *metricp;
9c675f5e259c19f9fdc40808439479131b32421eTimo Sirainen
9c675f5e259c19f9fdc40808439479131b32421eTimo Sirainen array_foreach(&metrics->metrics, metricp) {
5f08b0309190ec818d46bfe0e497468b30714a93Timo Sirainen stats_dist_reset((*metricp)->duration_stats);
9c675f5e259c19f9fdc40808439479131b32421eTimo Sirainen for (unsigned int i = 0; i < (*metricp)->fields_count; i++)
5f08b0309190ec818d46bfe0e497468b30714a93Timo Sirainen stats_dist_reset((*metricp)->fields[i].stats);
9c675f5e259c19f9fdc40808439479131b32421eTimo Sirainen }
9c675f5e259c19f9fdc40808439479131b32421eTimo Sirainen}
9c675f5e259c19f9fdc40808439479131b32421eTimo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstruct event_filter *
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstats_metrics_get_event_filter(struct stats_metrics *metrics)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen{
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen return metrics->filter;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen}
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstatic void
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstats_metric_event(struct metric *metric, struct event *event)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen{
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct timeval tv_start, tv_end;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen intmax_t duration = 0;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen if (event_get_last_send_time(event, &tv_end)) {
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen event_get_create_time(event, &tv_start);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen duration = timeval_diff_usecs(&tv_end, &tv_start);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen }
5f08b0309190ec818d46bfe0e497468b30714a93Timo Sirainen stats_dist_add(metric->duration_stats, duration);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen for (unsigned int i = 0; i < metric->fields_count; i++) {
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen const struct event_field *field =
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen event_find_field(event, metric->fields[i].field_key);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen if (field == NULL)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen continue;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen intmax_t num = 0;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen switch (field->value_type) {
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen case EVENT_FIELD_VALUE_TYPE_STR:
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen break;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen case EVENT_FIELD_VALUE_TYPE_INTMAX:
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen num = field->value.intmax;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen break;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen case EVENT_FIELD_VALUE_TYPE_TIMEVAL:
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen num = field->value.timeval.tv_sec * 1000000ULL +
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen field->value.timeval.tv_usec;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen break;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen }
5f08b0309190ec818d46bfe0e497468b30714a93Timo Sirainen stats_dist_add(metric->fields[i].stats, num);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen }
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen}
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenvoid stats_metrics_event(struct stats_metrics *metrics, struct event *event)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen{
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct event_filter_match_iter *iter;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct metric *metric;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen iter = event_filter_match_iter_init(metrics->filter, event);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen while ((metric = event_filter_match_iter_next(iter)) != NULL)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen stats_metric_event(metric, event);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen event_filter_match_iter_deinit(&iter);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen}
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstruct stats_metrics_iter {
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct stats_metrics *metrics;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen unsigned int idx;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen};
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstruct stats_metrics_iter *
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenstats_metrics_iterate_init(struct stats_metrics *metrics)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen{
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct stats_metrics_iter *iter;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen iter = i_new(struct stats_metrics_iter, 1);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen iter->metrics = metrics;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen return iter;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen}
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenconst struct metric *stats_metrics_iterate(struct stats_metrics_iter *iter)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen{
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct metric *const *metrics;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen unsigned int count;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen metrics = array_get(&iter->metrics->metrics, &count);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen if (iter->idx >= count)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen return NULL;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen return metrics[iter->idx++];
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen}
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainenvoid stats_metrics_iterate_deinit(struct stats_metrics_iter **_iter)
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen{
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen struct stats_metrics_iter *iter = *_iter;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen *_iter = NULL;
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen i_free(iter);
e9068f1c3326de0265d0ef542a0d7723f5f01bc8Timo Sirainen}