bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "lib.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "net.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "istream.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "str.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "strescape.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "write-full.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "master-service.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "doveadm.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "doveadm-print.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainenstatic void dump_timing(const char *const **args, unsigned int fields_count)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen{
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen unsigned int i, args_count = str_array_length(*args);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen if (args_count > fields_count)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen args_count = fields_count;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen for (i = 0; i < args_count; i++)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen doveadm_print((*args)[i]);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen *args += args_count;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen}
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
f46a703b2916bdda27e701f2f8305c0ce3d1e893Timo Sirainenstatic void stats_dump(const char *path, const char *const *fields, bool reset)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen{
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen struct istream *input;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen string_t *cmd = t_str_new(128);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen unsigned int i, fields_count = str_array_length(fields);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen char *line;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen int fd;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen fd = doveadm_connect(path);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen net_set_nonblock(fd, FALSE);
f46a703b2916bdda27e701f2f8305c0ce3d1e893Timo Sirainen str_append(cmd, "VERSION\tstats-reader-client\t2\t0\n");
f46a703b2916bdda27e701f2f8305c0ce3d1e893Timo Sirainen str_append(cmd, reset ? "DUMP-RESET" : "DUMP");
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen for (i = 0; i < fields_count; i++) {
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen str_append_c(cmd, '\t');
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen str_append_tabescaped(cmd, fields[i]);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen }
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen str_append_c(cmd, '\n');
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen if (write_full(fd, str_data(cmd), str_len(cmd)) < 0)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen i_fatal("write(%s) failed: %m", path);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen input = i_stream_create_fd_autoclose(&fd, (size_t)-1);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen if ((line = i_stream_read_next_line(input)) == NULL)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen i_fatal("%s: Failed to read VERSION line", path);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen else if (!version_string_verify(line, "stats-reader-server", 2)) {
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen i_fatal_status(EX_PROTOCOL,
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen "%s is not a compatible stats-reader socket", path);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen }
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen doveadm_print_header_simple("metric_name");
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen doveadm_print_header_simple("field");
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen for (i = 0; i < fields_count; i++)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen doveadm_print_header_simple(fields[i]);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen while ((line = i_stream_read_next_line(input)) != NULL) {
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen if (line[0] == '\0')
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen break;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen T_BEGIN {
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen const char *const *args =
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen t_strsplit_tabescaped_inplace(line);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen const char *metric_name = args[0];
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen doveadm_print(metric_name); args++;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen doveadm_print("duration");
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen dump_timing(&args, fields_count);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen while (*args != NULL) {
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen doveadm_print(metric_name);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen doveadm_print(*args); args++;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen dump_timing(&args, fields_count);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen }
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen } T_END;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen }
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen if (input->stream_errno != 0)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen i_fatal("read(%s) failed: %s", path, i_stream_get_error(input));
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen i_stream_destroy(&input);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen}
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainenstatic void
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainendoveadm_cmd_stats_dump(struct doveadm_cmd_context *cctx)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen{
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen const char *path;
f46a703b2916bdda27e701f2f8305c0ce3d1e893Timo Sirainen bool reset;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen if (!doveadm_cmd_param_str(cctx, "socket-path", &path))
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen path = t_strconcat(doveadm_settings->base_dir, "/stats-reader", NULL);
f46a703b2916bdda27e701f2f8305c0ce3d1e893Timo Sirainen if (!doveadm_cmd_param_bool(cctx, "reset", &reset))
f46a703b2916bdda27e701f2f8305c0ce3d1e893Timo Sirainen reset = FALSE;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen doveadm_print_init(DOVEADM_PRINT_TYPE_TAB);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen const char *const fields[] = {
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen "count", "sum", "min", "max", "avg", "median", "%95", NULL
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen };
f46a703b2916bdda27e701f2f8305c0ce3d1e893Timo Sirainen stats_dump(path, fields, reset);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen return;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen}
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainenstruct doveadm_cmd_ver2 doveadm_cmd_stats_dump_ver2 = {
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen .cmd = doveadm_cmd_stats_dump,
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen .name = "stats dump",
f46a703b2916bdda27e701f2f8305c0ce3d1e893Timo Sirainen .usage = "[-s <stats socket path>] [-r]",
285f3c4cf828ebe9ff345080aa1df3755613af29Timo SirainenDOVEADM_CMD_PARAMS_START
285f3c4cf828ebe9ff345080aa1df3755613af29Timo SirainenDOVEADM_CMD_PARAM('s', "socket-path", CMD_PARAM_STR, 0)
f46a703b2916bdda27e701f2f8305c0ce3d1e893Timo SirainenDOVEADM_CMD_PARAM('r', "reset", CMD_PARAM_BOOL, 0)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo SirainenDOVEADM_CMD_PARAMS_END
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen};