From a0dda8cc382c6904ebe7a425e6bf5bdff8880bf6 Mon Sep 17 00:00:00 2001 From: Aki Tuomi Date: Wed, 4 Oct 2023 08:34:02 +0300 Subject: [PATCH] stats: transport file - Add unix socket support --- src/stats/event-exporter-transport-file.c | 73 +++++++++++++++++++---- src/stats/event-exporter.h | 1 + src/stats/stats-metrics.c | 2 + src/stats/stats-settings.c | 3 +- 4 files changed, 65 insertions(+), 14 deletions(-) diff --git a/src/stats/event-exporter-transport-file.c b/src/stats/event-exporter-transport-file.c index 41cfe2d7b1..e7cf0ddd9e 100644 --- a/src/stats/event-exporter-transport-file.c +++ b/src/stats/event-exporter-transport-file.c @@ -1,10 +1,12 @@ /* Copyright (c) 2023 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "net.h" #include "ioloop.h" #include "str.h" #include "eacces-error.h" #include "ostream.h" +#include "ostream-unix.h" #include "event-exporter.h" #include @@ -17,6 +19,8 @@ struct exporter_file { struct ostream *output; int fd; time_t last_error; + unsigned int connect_timeout_msecs; + bool unix_socket:1; }; #define EXPORTER_LAST_ERROR_DELAY 60 @@ -57,12 +61,15 @@ void event_export_transport_file_deinit(void) } } -static struct exporter_file *exporter_file_init(const struct exporter *exporter) +static struct exporter_file *exporter_file_init(const struct exporter *exporter, + bool unix_socket) { struct exporter_file *node; node = i_new(struct exporter_file, 1); node->fname = i_strdup(t_strcut(exporter->transport_args, ' ')); node->fd = -1; + node->unix_socket = unix_socket; + node->connect_timeout_msecs = exporter->transport_timeout; node->next = exporter_file_list_head; exporter_file_list_head = node; event_export_transport_assign_context(exporter, node); @@ -78,12 +85,21 @@ static void exporter_file_open_error(struct exporter_file *node, const char *fun node->last_error = ioloop_time; } -static bool exporter_file_open(struct exporter_file *node) +static bool exporter_file_open_unix(struct exporter_file *node) +{ + node->fd = net_connect_unix_with_retries(node->fname , + node->connect_timeout_msecs); + if (node->fd == -1) { + if (ioloop_time - node->last_error > EXPORTER_LAST_ERROR_DELAY) + exporter_file_open_error(node, "connect"); + return FALSE; + } + node->output = o_stream_create_unix(node->fd, IO_BLOCK_SIZE); + return TRUE; +} + +static bool exporter_file_open_plain(struct exporter_file *node) { - if (likely(node->output != NULL && !node->output->closed)) - return TRUE; - o_stream_destroy(&node->output); - i_close_fd(&node->fd); node->fd = open(node->fname, O_CREAT|O_APPEND|O_WRONLY, 0600); if (node->fd == -1) { if (ioloop_time - node->last_error > EXPORTER_LAST_ERROR_DELAY) @@ -91,18 +107,27 @@ static bool exporter_file_open(struct exporter_file *node) return FALSE; } node->output = o_stream_create_fd_file(node->fd, UOFF_T_MAX, FALSE); + return TRUE; +} + +static bool exporter_file_open(struct exporter_file *node) +{ + if (likely(node->output != NULL && !node->output->closed)) + return TRUE; + o_stream_destroy(&node->output); + i_close_fd(&node->fd); + if (node->unix_socket) { + if (!exporter_file_open_unix(node)) + return FALSE; + } else if (!exporter_file_open_plain(node)) + return FALSE; o_stream_set_name(node->output, node->fname); return TRUE; } -void event_export_transport_file(const struct exporter *exporter, - const buffer_t *buf) +static void event_export_transport_file_write(struct exporter_file *node, + const buffer_t *buf) { - struct exporter_file *node = exporter->transport_context; - if (node == NULL) - node = exporter_file_init(exporter); - if (!exporter_file_open(node)) - return; const struct const_iovec vec[] = { { .iov_base = buf->data, .iov_len = buf->used }, { .iov_base = "\n", .iov_len = 1 } @@ -116,3 +141,25 @@ void event_export_transport_file(const struct exporter *exporter, o_stream_close(node->output); } } + +void event_export_transport_file(const struct exporter *exporter, + const buffer_t *buf) +{ + struct exporter_file *node = exporter->transport_context; + if (node == NULL) + node = exporter_file_init(exporter, FALSE); + if (!exporter_file_open(node)) + return; + event_export_transport_file_write(node, buf); +} + +void event_export_transport_unix(const struct exporter *exporter, + const buffer_t *buf) +{ + struct exporter_file *node = exporter->transport_context; + if (node == NULL) + node = exporter_file_init(exporter, TRUE); + if (!exporter_file_open(node)) + return; + event_export_transport_file_write(node, buf); +} diff --git a/src/stats/event-exporter.h b/src/stats/event-exporter.h index 8fdfeb85a5..b4622c23f6 100644 --- a/src/stats/event-exporter.h +++ b/src/stats/event-exporter.h @@ -14,6 +14,7 @@ void event_export_transport_http_post(const struct exporter *exporter, const buf void event_export_transport_http_post_deinit(void); void event_export_transport_log(const struct exporter *exporter, const buffer_t *buf); void event_export_transport_file(const struct exporter *exporter, const buffer_t *buf); +void event_export_transport_unix(const struct exporter *exporter, const buffer_t *buf); void event_export_transport_file_deinit(void); /* append a microsecond resolution RFC3339 UTC timestamp */ diff --git a/src/stats/stats-metrics.c b/src/stats/stats-metrics.c index ff5bce6643..694a33f05d 100644 --- a/src/stats/stats-metrics.c +++ b/src/stats/stats-metrics.c @@ -74,6 +74,8 @@ static void stats_exporters_add_set(struct stats_metrics *metrics, LOG_EXPORTER_LONG_FIELD_TRUNCATE_LEN; } else if (strcmp(set->transport, "file") == 0) { exporter->transport = event_export_transport_file; + } else if (strcmp(set->transport, "unix") == 0) { + exporter->transport = event_export_transport_unix; } else { i_unreached(); } diff --git a/src/stats/stats-settings.c b/src/stats/stats-settings.c index 276212f84d..d00b450f13 100644 --- a/src/stats/stats-settings.c +++ b/src/stats/stats-settings.c @@ -289,7 +289,8 @@ static bool stats_exporter_settings_check(void *_set, pool_t pool ATTR_UNUSED, } else if (strcmp(set->transport, "drop") == 0 || strcmp(set->transport, "http-post") == 0 || strcmp(set->transport, "log") == 0 || - strcmp(set->transport, "file") == 0) { + strcmp(set->transport, "file") == 0 || + strcmp(set->transport, "unix") == 0) { /* no-op */ } else { *error_r = t_strdup_printf("Unknown transport type '%s'", -- 2.47.3