]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm: Add new "stats dump" command
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 4 Dec 2017 19:56:29 +0000 (21:56 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 13 Dec 2017 11:22:17 +0000 (13:22 +0200)
src/doveadm/Makefile.am
src/doveadm/doveadm-cmd.c
src/doveadm/doveadm-cmd.h
src/doveadm/doveadm-stats.c [new file with mode: 0644]

index cc361180ce964997ceac35f4673ab75e8f9e62fc..eeab429ee152ede67c0e66ffd955c1328ea1780c 100644 (file)
@@ -83,6 +83,7 @@ doveadm_common_cmds = \
        doveadm-proxy.c \
        doveadm-replicator.c \
        doveadm-sis.c \
+       doveadm-stats.c \
        doveadm-oldstats.c \
        doveadm-who.c
 
index d4fdfba5e57f101975e9e24564cc92d4b2d91afc..11d8b47115a59497ab701a5cd8d0d09b633c42ff 100644 (file)
@@ -24,6 +24,7 @@ static struct doveadm_cmd_ver2 *doveadm_commands_ver2[] = {
        &doveadm_cmd_process_status_ver2,
        &doveadm_cmd_stop_ver2,
        &doveadm_cmd_reload_ver2,
+       &doveadm_cmd_stats_dump_ver2,
        &doveadm_cmd_oldstats_dump_ver2,
        &doveadm_cmd_oldstats_reset_ver2,
        &doveadm_cmd_penalty_ver2,
index 729d3eb0535318924a8b4808582ab6fa37e4efe6..eabd5e47c62d00a835130897de4beb76bffbf3d9 100644 (file)
@@ -154,6 +154,7 @@ extern struct doveadm_cmd_ver2 doveadm_cmd_service_status_ver2;
 extern struct doveadm_cmd_ver2 doveadm_cmd_process_status_ver2;
 extern struct doveadm_cmd_ver2 doveadm_cmd_stop_ver2;
 extern struct doveadm_cmd_ver2 doveadm_cmd_reload_ver2;
+extern struct doveadm_cmd_ver2 doveadm_cmd_stats_dump_ver2;
 extern struct doveadm_cmd_ver2 doveadm_cmd_oldstats_reset_ver2;
 extern struct doveadm_cmd_ver2 doveadm_cmd_oldstats_dump_ver2;
 extern struct doveadm_cmd_ver2 doveadm_cmd_oldstats_top_ver2;
diff --git a/src/doveadm/doveadm-stats.c b/src/doveadm/doveadm-stats.c
new file mode 100644 (file)
index 0000000..3ded756
--- /dev/null
@@ -0,0 +1,103 @@
+/* Copyright (c) 2017 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "net.h"
+#include "istream.h"
+#include "str.h"
+#include "strescape.h"
+#include "write-full.h"
+#include "master-service.h"
+#include "doveadm.h"
+#include "doveadm-print.h"
+
+static void dump_timing(const char *const **args, unsigned int fields_count)
+{
+       unsigned int i, args_count = str_array_length(*args);
+
+       if (args_count > fields_count)
+               args_count = fields_count;
+       for (i = 0; i < args_count; i++)
+               doveadm_print((*args)[i]);
+       *args += args_count;
+}
+
+static void stats_dump(const char *path, const char *const *fields)
+{
+       struct istream *input;
+       string_t *cmd = t_str_new(128);
+       unsigned int i, fields_count = str_array_length(fields);
+       char *line;
+       int fd;
+
+       fd = doveadm_connect(path);
+       net_set_nonblock(fd, FALSE);
+       str_append(cmd, "VERSION\tstats-reader-client\t2\t0\nDUMP");
+       for (i = 0; i < fields_count; i++) {
+               str_append_c(cmd, '\t');
+               str_append_tabescaped(cmd, fields[i]);
+       }
+       str_append_c(cmd, '\n');
+       if (write_full(fd, str_data(cmd), str_len(cmd)) < 0)
+               i_fatal("write(%s) failed: %m", path);
+
+       input = i_stream_create_fd_autoclose(&fd, (size_t)-1);
+       if ((line = i_stream_read_next_line(input)) == NULL)
+               i_fatal("%s: Failed to read VERSION line", path);
+       else if (!version_string_verify(line, "stats-reader-server", 2)) {
+               i_fatal_status(EX_PROTOCOL,
+                       "%s is not a compatible stats-reader socket", path);
+       }
+
+       doveadm_print_header_simple("metric_name");
+       doveadm_print_header_simple("field");
+       for (i = 0; i < fields_count; i++)
+               doveadm_print_header_simple(fields[i]);
+
+       while ((line = i_stream_read_next_line(input)) != NULL) {
+               if (line[0] == '\0')
+                       break;
+               T_BEGIN {
+                       const char *const *args =
+                               t_strsplit_tabescaped_inplace(line);
+
+                       const char *metric_name = args[0];
+                       doveadm_print(metric_name); args++;
+                       doveadm_print("duration");
+                       dump_timing(&args, fields_count);
+                       while (*args != NULL) {
+                               doveadm_print(metric_name);
+                               doveadm_print(*args); args++;
+                               dump_timing(&args, fields_count);
+                       }
+               } T_END;
+       }
+
+       if (input->stream_errno != 0)
+               i_fatal("read(%s) failed: %s", path, i_stream_get_error(input));
+       i_stream_destroy(&input);
+}
+
+static void
+doveadm_cmd_stats_dump(struct doveadm_cmd_context *cctx)
+{
+       const char *path;
+
+       if (!doveadm_cmd_param_str(cctx, "socket-path", &path))
+               path = t_strconcat(doveadm_settings->base_dir, "/stats-reader", NULL);
+
+       doveadm_print_init(DOVEADM_PRINT_TYPE_TAB);
+       const char *const fields[] = {
+               "count", "sum", "min", "max", "avg", "median", "%95", NULL
+       };
+       stats_dump(path, fields);
+       return;
+}
+
+struct doveadm_cmd_ver2 doveadm_cmd_stats_dump_ver2 = {
+       .cmd = doveadm_cmd_stats_dump,
+       .name = "stats dump",
+       .usage = "[-s <stats socket path>]",
+DOVEADM_CMD_PARAMS_START
+DOVEADM_CMD_PARAM('s', "socket-path", CMD_PARAM_STR, 0)
+DOVEADM_CMD_PARAMS_END
+};