]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
stats: transport file - Add unix socket support
authorAki Tuomi <aki.tuomi@open-xchange.com>
Wed, 4 Oct 2023 05:34:02 +0000 (08:34 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Mon, 30 Oct 2023 06:29:29 +0000 (06:29 +0000)
src/stats/event-exporter-transport-file.c
src/stats/event-exporter.h
src/stats/stats-metrics.c
src/stats/stats-settings.c

index 41cfe2d7b15131818af2d422cdf5d08270d086db..e7cf0ddd9e61ff94f4d71c76e5aaee30af95b323 100644 (file)
@@ -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 <sys/stat.h>
@@ -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);
+}
index 8fdfeb85a5debe86dbcc16b65bb4160be68c4e53..b4622c23f6efe67d84510effe5a830df1ddaf156 100644 (file)
@@ -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 */
index ff5bce6643638bf99a9b066195f1103b6403b45b..694a33f05d263adfdeabeb7b6053c87a3e695924 100644 (file)
@@ -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();
        }
index 276212f84db18ab86363a2610e1c528d40af5fc9..d00b450f13ad8500f6afdd14480bbd7b2b6405f1 100644 (file)
@@ -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'",