]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
stats: Change event exporters to be proper objects of type event_exporter_transport
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 29 Aug 2024 09:59:00 +0000 (12:59 +0300)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 17 Jan 2025 08:39:59 +0000 (10:39 +0200)
src/stats/client-reader.c
src/stats/event-exporter-transport-file.c
src/stats/event-exporter-transport-http-post.c
src/stats/event-exporter-transport-log.c
src/stats/event-exporter.c
src/stats/event-exporter.h
src/stats/stats-metrics.c
src/stats/stats-metrics.h

index 59d81c85ba797807baa4fc1deb6069ca0e7fab78..e9fabe44bb68802a2106a3582902ad2a3088dd30 100644 (file)
@@ -258,7 +258,7 @@ reader_client_input_args(struct connection *conn, const char *const *args)
        else if (strcmp(cmd, "DUMP-RESET") == 0)
                return reader_client_input_dump_reset(client, args);
        else if (strcmp(cmd, "REOPEN") == 0) {
-               event_exporter_transports_reopen();
+               event_exporters_reopen();
                o_stream_nsend(client->conn.output, "+\n", 2);
        }
        return 1;
index ebe4d7de334fa8902ae5646d1348c33af3d9685b..6a4ab8218fb06077bc38e5f99c09f681b458888e 100644 (file)
@@ -14,7 +14,8 @@
 #include <fcntl.h>
 
 struct file_event_exporter {
-       struct file_event_exporter *next;
+       struct event_exporter exporter;
+
        char *fname;
        struct ostream *output;
        int fd;
@@ -25,10 +26,10 @@ struct file_event_exporter {
 
 #define EXPORTER_LAST_ERROR_DELAY 60
 
-static struct file_event_exporter *exporter_file_list_head = NULL;
-
 static void exporter_file_close(struct file_event_exporter *node)
 {
+       if (node->fd == -1)
+               return;
        if (o_stream_finish(node->output) < 0) {
                i_error("write(%s) failed: %s", node->fname,
                        o_stream_get_error(node->output));
@@ -38,42 +39,33 @@ static void exporter_file_close(struct file_event_exporter *node)
        i_close_fd(&node->fd);
 }
 
-static void exporter_file_destroy(struct file_event_exporter **_node)
+static void event_exporter_file_deinit(struct event_exporter *_exporter)
 {
-       struct file_event_exporter *node = *_node;
-       if (node == NULL)
-               return;
-       *_node = NULL;
+       struct file_event_exporter *node =
+               container_of(_exporter, struct file_event_exporter, exporter);
 
        exporter_file_close(node);
        i_free(node->fname);
-       i_free(node);
 }
 
-static void event_exporter_file_deinit(void)
+static void
+exporter_file_init(struct file_event_exporter *node, bool unix_socket)
 {
-       struct file_event_exporter *node, *next = exporter_file_list_head;
-       exporter_file_list_head = NULL;
-       while (next != NULL) {
-               node = next;
-               next = node->next;
-               exporter_file_destroy(&node);
-       }
+       node->fname = i_strdup(t_strcut(node->exporter.transport_args, ' '));
+       node->fd = -1;
+       node->unix_socket = unix_socket;
+       node->connect_timeout_msecs = node->exporter.transport_timeout;
 }
 
-static struct file_event_exporter *
-exporter_file_init(const struct event_exporter *exporter, bool unix_socket)
+static int
+event_exporter_file_init(pool_t pool, struct event *event ATTR_UNUSED,
+                        struct event_exporter **exporter_r,
+                        const char **error_r ATTR_UNUSED)
 {
-       struct file_event_exporter *node;
-       node = i_new(struct file_event_exporter, 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);
-       return node;
+       struct file_event_exporter *node =
+               p_new(pool, struct file_event_exporter, 1);
+       *exporter_r = &node->exporter;
+       return 0;
 }
 
 static void exporter_file_open_error(struct file_event_exporter *node, const char *func)
@@ -143,41 +135,41 @@ static void event_exporter_file_write(struct file_event_exporter *node,
 }
 
 static void
-event_exporter_file_send(struct event_exporter *exporter, const buffer_t *buf)
+event_exporter_file_send(struct event_exporter *_exporter, const buffer_t *buf)
 {
-       struct file_event_exporter *node = exporter->transport_context;
-       if (node == NULL)
-               node = exporter_file_init(exporter, FALSE);
+       struct file_event_exporter *node =
+               container_of(_exporter, struct file_event_exporter, exporter);
+       if (node->fname == NULL)
+               exporter_file_init(node, FALSE);
        if (!exporter_file_open(node))
                return;
        event_exporter_file_write(node, buf);
 }
 
 static void
-event_exporter_unix_send(struct event_exporter *exporter, const buffer_t *buf)
+event_exporter_unix_send(struct event_exporter *_exporter,
+                        const buffer_t *buf)
 {
-       struct file_event_exporter *node = exporter->transport_context;
-       if (node == NULL)
-               node = exporter_file_init(exporter, TRUE);
+       struct file_event_exporter *node =
+               container_of(_exporter, struct file_event_exporter, exporter);
+       if (node->fname == NULL)
+               exporter_file_init(node, TRUE);
        if (!exporter_file_open(node))
                return;
        event_exporter_file_write(node, buf);
 }
 
-static void event_exporter_file_reopen(void)
+static void event_exporter_file_reopen(struct event_exporter *_exporter)
 {
-       /* close all files, but not unix sockets */
-       struct file_event_exporter *node = exporter_file_list_head;
-       while (node != NULL) {
-               if (!node->unix_socket)
-                       exporter_file_close(node);
-               node = node->next;
-       }
+       struct file_event_exporter *node =
+               container_of(_exporter, struct file_event_exporter, exporter);
+       exporter_file_close(node);
 }
 
 const struct event_exporter_transport event_exporter_transport_file = {
        .name = "file",
 
+       .init = event_exporter_file_init,
        .send = event_exporter_file_send,
        .reopen = event_exporter_file_reopen,
 };
@@ -185,7 +177,7 @@ const struct event_exporter_transport event_exporter_transport_file = {
 const struct event_exporter_transport event_exporter_transport_unix = {
        .name = "unix",
 
+       .init = event_exporter_file_init,
        .deinit = event_exporter_file_deinit,
        .send = event_exporter_unix_send,
-       .reopen = event_exporter_file_reopen,
 };
index 333da70a612963b81b387b2a225e6578df1cc2d6..0674e1e26493427c8211f9aa1a7139012f4d9bb6 100644 (file)
@@ -14,7 +14,8 @@
 /* the http client used to export all events with exporter=http-post */
 static struct http_client *exporter_http_client;
 
-static void event_exporter_http_post_deinit(void)
+static void
+event_exporter_http_post_deinit(struct event_exporter *exporter ATTR_UNUSED)
 {
        if (exporter_http_client != NULL)
                http_client_deinit(&exporter_http_client);
index 262a2ac1daa00260f730f0e615bc694de07a387c..464cb15d542413dcbf02ca4bd85b6d644ec0a47f 100644 (file)
@@ -5,6 +5,19 @@
 #include "str.h"
 #include "event-exporter.h"
 
+#define LOG_EXPORTER_LONG_FIELD_TRUNCATE_LEN 1000
+
+static int event_exporter_log_init(pool_t pool, struct event *event ATTR_UNUSED,
+                                  struct event_exporter **exporter_r,
+                                  const char **error_r ATTR_UNUSED)
+{
+       struct event_exporter *exporter = p_new(pool, struct event_exporter, 1);
+       exporter->format_max_field_len =
+               LOG_EXPORTER_LONG_FIELD_TRUNCATE_LEN;
+       *exporter_r = exporter;
+       return 0;
+}
+
 static void
 event_exporter_log_send(struct event_exporter *exporter ATTR_UNUSED,
                        const buffer_t *buf)
@@ -15,5 +28,6 @@ event_exporter_log_send(struct event_exporter *exporter ATTR_UNUSED,
 const struct event_exporter_transport event_exporter_transport_log = {
        .name = "log",
 
+       .init = event_exporter_log_init,
        .send = event_exporter_log_send,
 };
index 0fda4205fd0426c176b152560c111cd9a03a6e7f..027b00e57129399b33041f3a54c97e9a61b5fe2b 100644 (file)
@@ -1,6 +1,7 @@
 /* Copyright (c) 2024 Dovecot authors, see the included COPYING file */
 
 #include "stats-common.h"
+#include "array.h"
 #include "event-exporter.h"
 
 static const struct event_exporter_transport *event_exporter_transports[] = {
@@ -11,6 +12,8 @@ static const struct event_exporter_transport *event_exporter_transports[] = {
        &event_exporter_transport_log,
 };
 
+static ARRAY(struct event_exporter *) event_exporters;
+
 const struct event_exporter_transport *
 event_exporter_transport_find(const char *name)
 {
@@ -21,18 +24,44 @@ event_exporter_transport_find(const char *name)
        return NULL;
 }
 
-void event_exporter_transports_reopen(void)
+void event_exporters_reopen(void)
 {
-       for (unsigned int i = 0; i < N_ELEMENTS(event_exporter_transports); i++) {
-               if (event_exporter_transports[i]->reopen != NULL)
-                       event_exporter_transports[i]->reopen();
+       struct event_exporter *exporter;
+
+       array_foreach_elem(&event_exporters, exporter) {
+               if (exporter->transport->reopen != NULL)
+                       exporter->transport->reopen(exporter);
        }
 }
 
-void event_exporter_transports_deinit(void)
+void event_exporters_deinit(void)
 {
-       for (unsigned int i = 0; i < N_ELEMENTS(event_exporter_transports); i++) {
-               if (event_exporter_transports[i]->reopen != NULL)
-                       event_exporter_transports[i]->deinit();
+       struct event_exporter *exporter;
+
+       if (!array_is_created(&event_exporters))
+               return;
+
+       array_foreach_elem(&event_exporters, exporter) {
+               if (exporter->transport->deinit != NULL)
+                       exporter->transport->deinit(exporter);
        }
 }
+
+int event_exporter_init(const struct event_exporter_transport *transport,
+                       pool_t pool, struct event *event,
+                       struct event_exporter **exporter_r,
+                       const char **error_r)
+{
+       struct event_exporter *exporter;
+
+       if (transport->init == NULL)
+               exporter = p_new(pool, struct event_exporter, 1);
+       else if (transport->init(pool, event, &exporter, error_r) < 0)
+               return -1;
+
+       if (!array_is_created(&event_exporters))
+               i_array_init(&event_exporters, 4);
+       array_push_back(&event_exporters, &exporter);
+       *exporter_r = exporter;
+       return 0;
+}
index 534d4f8e1021f4adde6ca55167df0dce7c3b4200..5674e974f4bf88d6ca3c28cff17b86cfd061a34a 100644 (file)
@@ -6,12 +6,14 @@
 struct event_exporter_transport {
        const char *name;
 
-       void (*deinit)(void);
+       int (*init)(pool_t pool, struct event *event,
+                   struct event_exporter **exporter_r, const char **error_r);
+       void (*deinit)(struct event_exporter *exporter);
 
        /* function to send the event */
        void (*send)(struct event_exporter *exporter, const buffer_t *buf);
 
-       void (*reopen)(void);
+       void (*reopen)(struct event_exporter *exporter);
 };
 
 extern const struct event_exporter_transport event_exporter_transport_drop;
@@ -22,8 +24,14 @@ extern const struct event_exporter_transport event_exporter_transport_log;
 
 const struct event_exporter_transport *
 event_exporter_transport_find(const char *name);
-void event_exporter_transports_reopen(void);
-void event_exporter_transports_deinit(void);
+
+void event_exporters_reopen(void);
+void event_exporters_deinit(void);
+
+int event_exporter_init(const struct event_exporter_transport *transport,
+                       pool_t pool, struct event *event,
+                       struct event_exporter **exporter_r,
+                       const char **error_r);
 
 /* fmt functions */
 void event_export_fmt_json(const struct metric *metric, struct event *event, buffer_t *dest);
@@ -43,8 +51,4 @@ void event_export_helper_fmt_categories(string_t *dest,
                                        void (*append)(string_t *, const char *),
                                        const char *separator);
 
-/* assign transport context to a event exporter */
-void event_export_transport_assign_context(const struct event_exporter *exporter,
-                                          void *context);
-
 #endif
index c862f00aea82673dfbf8cbdfea8c2411f0b5f659..e753492bfcd33e13b5adb343e12627ed999bc79c 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <ctype.h>
 
-#define LOG_EXPORTER_LONG_FIELD_TRUNCATE_LEN 1000
 #define STATS_SUB_METRIC_MAX_LENGTH 256
 
 struct stats_metrics {
@@ -32,12 +31,18 @@ static struct metric *
 stats_metric_sub_metric_alloc(struct metric *metric, const char *name, pool_t pool);
 static void stats_metric_free(struct metric *metric);
 
-static void stats_exporters_add_set(struct stats_metrics *metrics,
-                                   const struct stats_exporter_settings *set)
+static int stats_exporters_add_set(struct stats_metrics *metrics,
+                                  struct event *event,
+                                  const struct stats_exporter_settings *set,
+                                  const char **error_r)
 {
+       const struct event_exporter_transport *transport =
+               set->parsed_transport;
        struct event_exporter *exporter;
 
-       exporter = p_new(metrics->pool, struct event_exporter, 1);
+       if (event_exporter_init(transport, metrics->pool, event,
+                               &exporter, error_r) < 0)
+               return -1;
        exporter->name = p_strdup(metrics->pool, set->name);
        exporter->transport_args = p_strdup(metrics->pool, set->transport_args);
        exporter->transport_timeout = set->transport_timeout;
@@ -61,21 +66,11 @@ static void stats_exporters_add_set(struct stats_metrics *metrics,
                i_unreached();
        }
 
-       if (strcmp(set->parsed_transport->name, "log") == 0) {
-               exporter->format_max_field_len =
-                       LOG_EXPORTER_LONG_FIELD_TRUNCATE_LEN;
-       }
-       exporter->transport = set->parsed_transport;
+       exporter->transport = transport;
        exporter->transport_args = set->transport_args;
 
        array_push_back(&metrics->exporters, &exporter);
-}
-
-void event_export_transport_assign_context(const struct event_exporter *exporter,
-                                          void *context)
-{
-       struct event_exporter *ptr = (struct event_exporter *)exporter;
-       ptr->transport_context = context;
+       return 0;
 }
 
 static int stats_exporters_add_filter(struct stats_metrics *metrics,
@@ -94,7 +89,12 @@ static int stats_exporters_add_filter(struct stats_metrics *metrics,
                *error_r = "Exporter name can't be empty";
                ret = -1;
        } else {
-               stats_exporters_add_set(metrics, set);
+               struct event *event = event_create(metrics->event);
+               event_set_ptr(event, SETTINGS_EVENT_FILTER_NAME,
+                       p_strdup_printf(event_get_pool(event),
+                                       "event_exporter/%s", filter_name));
+               ret = stats_exporters_add_set(metrics, event, set, error_r);
+               event_unref(&event);
        }
        settings_free(set);
        return ret;
@@ -371,7 +371,7 @@ void stats_metrics_deinit(struct stats_metrics **_metrics)
 
        *_metrics = NULL;
 
-       event_exporter_transports_deinit();
+       event_exporters_deinit();
 
        array_foreach_elem(&metrics->metrics, metric)
                stats_metric_free(metric);
index 8a03ad219873a57cc24365cf4a0e9678351b27bd..762f692c8f15376a426bc16d0be3a5a6b24a6c48 100644 (file)
@@ -35,7 +35,6 @@ struct event_exporter {
         */
        const char *transport_args;
        unsigned int transport_timeout;
-       void *transport_context;
 
        const struct event_exporter_transport *transport;
 };