]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
stats: Dump sub-metrics
authorAki Tuomi <aki.tuomi@open-xchange.com>
Sun, 1 Dec 2019 14:06:42 +0000 (16:06 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 20 Dec 2019 08:11:27 +0000 (08:11 +0000)
src/stats/client-reader.c

index 84423e0c87a897444496c610e3cafb8f236078ad..bd220ea03e36c4965b78d09446ea6100a0daae05 100644 (file)
@@ -1,6 +1,7 @@
 /* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "array.h"
 #include "str.h"
 #include "stats-dist.h"
 #include "strescape.h"
@@ -65,27 +66,57 @@ static void reader_client_dump_stats(string_t *str, struct stats_dist *stats,
        }
 }
 
+static void reader_client_dump_metric(string_t *str, const struct metric *metric,
+                                     const char *const *fields)
+{
+       reader_client_dump_stats(str, metric->duration_stats, fields);
+       for (unsigned int i = 0; i < metric->fields_count; i++) {
+               str_append_c(str, '\t');
+               str_append_tabescaped(str, metric->fields[i].field_key);
+               reader_client_dump_stats(str, metric->fields[i].stats, fields);
+       }
+       str_append_c(str, '\n');
+}
+
+static void
+reader_client_dump_sub_metrics(struct ostream *output, const struct metric *metric,
+                              const char *sub_name, const char *const *fields)
+{
+       size_t pos;
+       struct metric *const *sub_metrics;
+       if (!array_is_created(&metric->sub_metrics))
+               return;
+       string_t *str = t_str_new(128);
+       str_append_tabescaped(str, sub_name);
+       str_append_c(str, '_');
+       pos = str->used;
+
+       array_foreach(&metric->sub_metrics, sub_metrics) {
+               str_append_tabescaped(str, (*sub_metrics)->sub_name);
+               reader_client_dump_metric(str, *sub_metrics, fields);
+               o_stream_nsend(output, str_data(str), str_len(str));
+               str_truncate(str, pos);
+               reader_client_dump_sub_metrics(output, *sub_metrics,
+                                              str_c(str), fields);
+       }
+}
+
 static int
 reader_client_input_dump(struct reader_client *client, const char *const *args)
 {
        struct stats_metrics_iter *iter;
        const struct metric *metric;
-       string_t *str = t_str_new(128);
 
        o_stream_cork(client->conn.output);
        iter = stats_metrics_iterate_init(client->metrics);
-       while ((metric = stats_metrics_iterate(iter)) != NULL) {
-               str_truncate(str, 0);
+       while ((metric = stats_metrics_iterate(iter)) != NULL) T_BEGIN {
+               string_t *str = t_str_new(128);
                str_append_tabescaped(str, metric->name);
-               reader_client_dump_stats(str, metric->duration_stats, args);
-               for (unsigned int i = 0; i < metric->fields_count; i++) {
-                       str_append_c(str, '\t');
-                       str_append_tabescaped(str, metric->fields[i].field_key);
-                       reader_client_dump_stats(str, metric->fields[i].stats, args);
-               }
-               str_append_c(str, '\n');
+               reader_client_dump_metric(str, metric, args);
                o_stream_nsend(client->conn.output, str_data(str), str_len(str));
-       }
+               reader_client_dump_sub_metrics(client->conn.output, metric,
+                                              metric->name, args);
+       } T_END;
        o_stream_nsend(client->conn.output, "\n", 1);
        stats_metrics_iterate_deinit(&iter);
        o_stream_uncork(client->conn.output);