client-reader.c \
client-writer.c \
client-http.c \
+ event-exporter.c \
event-exporter-fmt.c \
event-exporter-fmt-json.c \
event-exporter-fmt-none.c \
#include "master-service.h"
#include "stats-metrics.h"
#include "stats-settings.h"
+#include "event-exporter.h"
#include "client-reader.h"
#include "client-writer.h"
#include "event-exporter.h"
else if (strcmp(cmd, "DUMP-RESET") == 0)
return reader_client_input_dump_reset(client, args);
else if (strcmp(cmd, "REOPEN") == 0) {
- event_export_transport_file_reopen();
+ event_exporter_transports_reopen();
o_stream_nsend(client->conn.output, "+\n", 2);
}
return 1;
#include "lib.h"
#include "event-exporter.h"
-void event_export_transport_drop(const struct exporter *exporter ATTR_UNUSED,
- const buffer_t *buf ATTR_UNUSED)
+static void
+event_exporter_drop_send(struct exporter *exporter ATTR_UNUSED,
+ const buffer_t *buf ATTR_UNUSED)
{
}
+
+const struct event_exporter_transport event_exporter_transport_drop = {
+ .name = "drop",
+
+ .send = event_exporter_drop_send,
+};
i_free(node);
}
-void event_export_transport_file_deinit(void)
+static void event_exporter_file_deinit(void)
{
struct exporter_file *node, *next = exporter_file_list_head;
exporter_file_list_head = NULL;
return TRUE;
}
-static void event_export_transport_file_write(struct exporter_file *node,
- const buffer_t *buf)
+static void event_exporter_file_write(struct exporter_file *node,
+ const buffer_t *buf)
{
const struct const_iovec vec[] = {
{ .iov_base = buf->data, .iov_len = buf->used },
}
}
-void event_export_transport_file(const struct exporter *exporter,
- const buffer_t *buf)
+static void
+event_exporter_file_send(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);
+ event_exporter_file_write(node, buf);
}
-void event_export_transport_unix(const struct exporter *exporter,
- const buffer_t *buf)
+static void
+event_exporter_unix_send(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);
+ event_exporter_file_write(node, buf);
}
-void event_export_transport_file_reopen(void)
+static void event_exporter_file_reopen(void)
{
/* close all files, but not unix sockets */
struct exporter_file *node = exporter_file_list_head;
node = node->next;
}
}
+
+const struct event_exporter_transport event_exporter_transport_file = {
+ .name = "file",
+
+ .send = event_exporter_file_send,
+ .reopen = event_exporter_file_reopen,
+};
+
+const struct event_exporter_transport event_exporter_transport_unix = {
+ .name = "unix",
+
+ .deinit = event_exporter_file_deinit,
+ .send = event_exporter_unix_send,
+ .reopen = event_exporter_file_reopen,
+};
/* the http client used to export all events with exporter=http-post */
static struct http_client *exporter_http_client;
-void event_export_transport_http_post_deinit(void)
+static void event_exporter_http_post_deinit(void)
{
if (exporter_http_client != NULL)
http_client_deinit(&exporter_http_client);
suppressed = 0;
}
-void event_export_transport_http_post(const struct exporter *exporter,
- const buffer_t *buf)
+static void
+event_exporter_http_post_send(struct exporter *exporter, const buffer_t *buf)
{
struct http_client_request *req;
http_client_request_set_timeout_msecs(req, exporter->transport_timeout);
http_client_request_submit(req);
}
+
+const struct event_exporter_transport event_exporter_transport_http_post = {
+ .name = "http-post",
+
+ .deinit = event_exporter_http_post_deinit,
+ .send = event_exporter_http_post_send,
+};
#include "str.h"
#include "event-exporter.h"
-void event_export_transport_log(const struct exporter *exporter ATTR_UNUSED,
- const buffer_t *buf)
+static void
+event_exporter_log_send(struct exporter *exporter ATTR_UNUSED,
+ const buffer_t *buf)
{
i_info("%.*s", (int)buf->used, (const char *)buf->data);
}
+
+const struct event_exporter_transport event_exporter_transport_log = {
+ .name = "log",
+
+ .send = event_exporter_log_send,
+};
--- /dev/null
+/* Copyright (c) 2024 Dovecot authors, see the included COPYING file */
+
+#include "stats-common.h"
+#include "event-exporter.h"
+
+static const struct event_exporter_transport *event_exporter_transports[] = {
+ &event_exporter_transport_drop,
+ &event_exporter_transport_file,
+ &event_exporter_transport_unix,
+ &event_exporter_transport_http_post,
+ &event_exporter_transport_log,
+};
+
+const struct event_exporter_transport *
+event_exporter_transport_find(const char *name)
+{
+ for (unsigned int i = 0; i < N_ELEMENTS(event_exporter_transports); i++) {
+ if (strcmp(event_exporter_transports[i]->name, name) == 0)
+ return event_exporter_transports[i];
+ }
+ return NULL;
+}
+
+void event_exporter_transports_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();
+ }
+}
+
+void event_exporter_transports_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();
+ }
+}
#include "stats-metrics.h"
+struct event_exporter_transport {
+ const char *name;
+
+ void (*deinit)(void);
+
+ /* function to send the event */
+ void (*send)(struct exporter *exporter, const buffer_t *buf);
+
+ void (*reopen)(void);
+};
+
+extern const struct event_exporter_transport event_exporter_transport_drop;
+extern const struct event_exporter_transport event_exporter_transport_file;
+extern const struct event_exporter_transport event_exporter_transport_unix;
+extern const struct event_exporter_transport event_exporter_transport_http_post;
+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);
+
/* fmt functions */
void event_export_fmt_json(const struct metric *metric, struct event *event, buffer_t *dest);
void event_export_fmt_none(const struct metric *metric, struct event *event, buffer_t *dest);
void event_export_fmt_tabescaped_text(const struct metric *metric, struct event *event, buffer_t *dest);
-/* transport functions */
-void event_export_transport_drop(const struct exporter *exporter, const buffer_t *buf);
-void event_export_transport_http_post(const struct exporter *exporter, const buffer_t *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_reopen(void);
-void event_export_transport_file_deinit(void);
-
/* append a microsecond resolution RFC3339 UTC timestamp */
void event_export_helper_fmt_rfc3339_time(string_t *dest, const struct timeval *time);
/* append a microsecond resolution unix timestamp in seconds (i.e., %u.%06u) */
i_unreached();
}
- /* TODO: The following should be plugable.
- *
- * Note: Make sure to mirror any changes to the below code in
- * stats_exporter_settings_check().
- */
- if (strcmp(set->driver, "drop") == 0) {
- exporter->transport = event_export_transport_drop;
- } else if (strcmp(set->driver, "http-post") == 0) {
- exporter->transport = event_export_transport_http_post;
- } else if (strcmp(set->driver, "log") == 0) {
- exporter->transport = event_export_transport_log;
+ if (strcmp(set->parsed_transport->name, "log") == 0) {
exporter->format_max_field_len =
LOG_EXPORTER_LONG_FIELD_TRUNCATE_LEN;
- } else if (strcmp(set->driver, "file") == 0) {
- exporter->transport = event_export_transport_file;
- } else if (strcmp(set->driver, "unix") == 0) {
- exporter->transport = event_export_transport_unix;
- } else {
- i_unreached();
}
-
+ exporter->transport = set->parsed_transport;
exporter->transport_args = set->transport_args;
array_push_back(&metrics->exporters, &exporter);
stats_metric_free(sub_metric);
}
-static void stats_export_deinit(void)
-{
- /* no need for event_export_transport_drop_deinit() - no-op */
- event_export_transport_http_post_deinit();
- /* no need for event_export_transport_log_deinit() - no-op */
- event_export_transport_file_deinit();
-}
-
void stats_metrics_deinit(struct stats_metrics **_metrics)
{
struct stats_metrics *metrics = *_metrics;
*_metrics = NULL;
- stats_export_deinit();
+ event_exporter_transports_deinit();
array_foreach_elem(&metrics->metrics, metric)
stats_metric_free(metric);
stats_export_event(struct metric *metric, struct event *oldevent)
{
const struct metric_export_info *info = &metric->export_info;
- const struct exporter *exporter = info->exporter;
+ struct exporter *exporter = info->exporter;
struct event *event;
i_assert(exporter != NULL);
buf = t_buffer_create(128);
exporter->format(metric, event, buf);
- exporter->transport(exporter, buf);
+ exporter->transport->send(exporter, buf);
} T_END;
event_unref(&event);
unsigned int transport_timeout;
void *transport_context;
- /* function to send the event */
- void (*transport)(const struct exporter *, const buffer_t *);
+ const struct event_exporter_transport *transport;
};
struct metric_export_info {
- const struct exporter *exporter;
+ struct exporter *exporter;
enum event_exporter_includes {
EVENT_EXPORTER_INCL_NONE = 0,
#include "settings.h"
#include "service-settings.h"
#include "stats-settings.h"
+#include "event-exporter.h"
#include "array.h"
#include "str.h"
#include "var-expand.h"
return FALSE;
}
- /* TODO: The following should be plugable.
- *
- * Note: Make sure to mirror any changes to the below code in
- * stats_exporters_add_set().
- */
if (set->driver[0] == '\0')
set->driver = set->name;
- if (strcmp(set->driver, "drop") == 0 ||
- strcmp(set->driver, "http-post") == 0 ||
- strcmp(set->driver, "log") == 0 ||
- strcmp(set->driver, "file") == 0 ||
- strcmp(set->driver, "unix") == 0) {
- /* no-op */
- } else {
+#ifndef CONFIG_BINARY
+ set->parsed_transport = event_exporter_transport_find(set->driver);
+ if (set->parsed_transport == NULL) {
*error_r = t_strdup_printf("Unknown evente_exporter_driver: %s",
set->driver);
return FALSE;
}
+#endif
if (!parse_format_args(set, error_r))
return FALSE;
/* parsed values */
enum event_exporter_time_fmt parsed_time_format;
+ const struct event_exporter_transport *parsed_transport;
};
/* <settings checks> */