From: Josef 'Jeff' Sipek Date: Thu, 4 Apr 2019 11:24:50 +0000 (+0300) Subject: stats: event export - Add http-post transport support X-Git-Tag: 2.3.9~479 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=541859b22208ed54cba1066134313816d886be49;p=thirdparty%2Fdovecot%2Fcore.git stats: event export - Add http-post transport support This commit adds support for transport=http-post. The value of transport_args is used as the HTTP POST URL. --- diff --git a/src/stats/Makefile.am b/src/stats/Makefile.am index 3be93f38e0..0a5106b1ab 100644 --- a/src/stats/Makefile.am +++ b/src/stats/Makefile.am @@ -6,6 +6,7 @@ AM_CPPFLAGS = \ -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) \ @@ -20,6 +21,7 @@ stats_SOURCES = \ 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 \ diff --git a/src/stats/event-exporter-transport-http-post.c b/src/stats/event-exporter-transport-http-post.c new file mode 100644 index 0000000000..9ca06e93ca --- /dev/null +++ b/src/stats/event-exporter-transport-http-post.c @@ -0,0 +1,61 @@ +/* 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); +} diff --git a/src/stats/event-exporter.h b/src/stats/event-exporter.h index a203f45215..c006bbe410 100644 --- a/src/stats/event-exporter.h +++ b/src/stats/event-exporter.h @@ -9,6 +9,8 @@ void event_export_fmt_none(const struct metric *metric, struct event *event, buf /* 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 */ diff --git a/src/stats/stats-metrics.c b/src/stats/stats-metrics.c index 20763603c4..1981375773 100644 --- a/src/stats/stats-metrics.c +++ b/src/stats/stats-metrics.c @@ -81,6 +81,8 @@ static void stats_exporters_add_set(struct stats_metrics *metrics, */ 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 { @@ -218,6 +220,7 @@ static void stats_metric_free(struct metric *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 */ } diff --git a/src/stats/stats-settings.c b/src/stats/stats-settings.c index 505552bc81..9b2c01ad3e 100644 --- a/src/stats/stats-settings.c +++ b/src/stats/stats-settings.c @@ -251,6 +251,7 @@ static bool stats_exporter_settings_check(void *_set, pool_t pool ATTR_UNUSED, *error_r = "Exporter transport name can't be empty"; return FALSE; } else if (strcmp(set->transport, "drop") == 0 || + strcmp(set->transport, "http-post") == 0 || strcmp(set->transport, "log") == 0) { /* no-op */ } else {