-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib-settings \
-I$(top_srcdir)/src/lib-master \
+ -I$(top_srcdir)/src/lib-http \
$(BINARY_CFLAGS)
stats_LDADD = $(LIBDOVECOT) \
event-exporter-fmt-json.c \
event-exporter-fmt-none.c \
event-exporter-transport-drop.c \
+ event-exporter-transport-http-post.c \
event-exporter-transport-log.c \
main.c \
stats-event-category.c \
--- /dev/null
+/* Copyright (c) 2019 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "str.h"
+#include "event-exporter.h"
+#include "http-client.h"
+
+#define EXPORT_HTTP_TIMEOUT 50 /* msec */
+
+/* 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)
+{
+ if (exporter_http_client != NULL)
+ http_client_deinit(&exporter_http_client);
+}
+
+static void response_fxn(const struct http_response *response,
+ void *context ATTR_UNUSED)
+{
+ static time_t last_log;
+ static unsigned suppressed;
+
+ if (http_response_is_success(response))
+ return;
+
+ if (last_log == ioloop_time) {
+ suppressed++;
+ return; /* don't spam the log */
+ }
+
+ if (suppressed == 0)
+ i_error("Failed to export event via HTTP POST: %d %s",
+ response->status, response->reason);
+ else
+ i_error("Failed to export event via HTTP POST: %d %s (%u more errors suppressed)",
+ response->status, response->reason, suppressed);
+
+ last_log = ioloop_time;
+ suppressed = 0;
+}
+
+void event_export_transport_http_post(const struct exporter *exporter,
+ const buffer_t *buf)
+{
+ struct http_client_request *req;
+
+ if (exporter_http_client == NULL)
+ exporter_http_client = http_client_init(NULL);
+
+ req = http_client_request_url_str(exporter_http_client, "POST",
+ exporter->transport_args,
+ response_fxn, NULL);
+ http_client_request_add_header(req, "Content-Type", exporter->format_mime_type);
+ http_client_request_set_payload_data(req, buf->data, buf->used);
+
+ http_client_request_set_timeout_msecs(req, EXPORT_HTTP_TIMEOUT);
+ http_client_request_submit(req);
+}
/* 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);
/* append a microsecond resolution RFC3339 UTC timestamp */
*/
if (strcmp(set->transport, "drop") == 0) {
exporter->transport = event_export_transport_drop;
+ } else if (strcmp(set->transport, "http-post") == 0) {
+ exporter->transport = event_export_transport_http_post;
} else if (strcmp(set->transport, "log") == 0) {
exporter->transport = event_export_transport_log;
} else {
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 */
}