stats-client.c revision bcb4e51a409d94ae670de96afb8483a4f7855294
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
5fe5ea74285e2fc0fbf7568c53f251aa894650fbTimo Sirainen#define STATS_CLIENT_RECONNECT_INTERVAL_MSECS (10*1000)
e815af0640b38444b31eadfaa1673bcb422e1573Timo Sirainenstatic void stats_client_connect(struct stats_client *client);
1a266561b099269bef75eee1a3742e61130ef780Timo Sirainenclient_handshake_filter(const char *const *args, struct event_filter **filter_r,
5fe5ea74285e2fc0fbf7568c53f251aa894650fbTimo Sirainen const char **error_r)
a33b41b1dc19c692b1283049ec4de492fdadeb9aTimo Sirainen if (!event_filter_import_unescaped(*filter_r, args+1, error_r)) {
a33b41b1dc19c692b1283049ec4de492fdadeb9aTimo Sirainenstats_client_handshake(struct stats_client *client, const char *const *args)
a33b41b1dc19c692b1283049ec4de492fdadeb9aTimo Sirainen if (client_handshake_filter(args, &filter, &error) < 0) {
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen i_error("stats: Received invalid handshake: %s (input: %s)",
a33b41b1dc19c692b1283049ec4de492fdadeb9aTimo Sirainen client->handshake_received_at_least_once = TRUE;
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen /* Filter is already set. It becomes a bit complicated to
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen change it. Since it's most likely exactly the same filter
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen anyway, just keep the old one. */
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen if (event_get_global_debug_send_filter() != NULL) {
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen /* merge into the global debug send filter */
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen event_filter_merge(event_get_global_debug_send_filter(),
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen /* no global filter yet - use this */
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen event_set_global_debug_send_filter(client->filter);
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainenstats_client_input_args(struct connection *conn, const char *const *args)
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen struct stats_client *client = (struct stats_client *)conn;
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen i_error("stats: Received unexpected input: %s",
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainenstatic void stats_client_reconnect(struct stats_client *client)
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainenstatic void stats_client_destroy(struct connection *conn)
a33b41b1dc19c692b1283049ec4de492fdadeb9aTimo Sirainen struct stats_client *client = (struct stats_client *)conn;
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen unsigned int reconnect_msecs = STATS_CLIENT_RECONNECT_INTERVAL_MSECS;
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen /* after reconnection the IDs need to be re-sent */
8ad2759cf4073e3bf4fcb9222a86e2153ed31875Timo Sirainen for (event = events_get_head(); event != NULL; event = event->next)
a33b41b1dc19c692b1283049ec4de492fdadeb9aTimo Sirainen /* waiting for stats handshake to finish */
a33b41b1dc19c692b1283049ec4de492fdadeb9aTimo Sirainen } else if (conn->connect_finished.tv_sec != 0) {
a0261d4fe4dfd422a051e474482e88785c04ee41Timo Sirainen if (msecs_since_connected >= STATS_CLIENT_RECONNECT_INTERVAL_MSECS) {
a33b41b1dc19c692b1283049ec4de492fdadeb9aTimo Sirainen /* reconnect immdiately */
a33b41b1dc19c692b1283049ec4de492fdadeb9aTimo Sirainen /* wait for reconnect interval since we last
a33b41b1dc19c692b1283049ec4de492fdadeb9aTimo Sirainen were connected. */
1de2b5a16a455e018d8cbf72ee114d4b5d557a48Timo Sirainen reconnect_msecs = STATS_CLIENT_RECONNECT_INTERVAL_MSECS -
a0261d4fe4dfd422a051e474482e88785c04ee41Timo Sirainenstatic const struct connection_settings stats_client_set = {
a0261d4fe4dfd422a051e474482e88785c04ee41Timo Sirainenstatic const struct connection_vfuncs stats_client_vfuncs = {
a0261d4fe4dfd422a051e474482e88785c04ee41Timo Sirainenstatic struct event *stats_event_get_parent(struct event *event)
a0261d4fe4dfd422a051e474482e88785c04ee41Timo Sirainen unsigned int count;
a0261d4fe4dfd422a051e474482e88785c04ee41Timo Sirainen if (parent == NULL || parent->id_sent_to_stats)
a0261d4fe4dfd422a051e474482e88785c04ee41Timo Sirainen /* avoid sending unnecessary events that don't add anything */
553667c748977991590854426255e1c34a615f24Timo Sirainenstatic void stats_event_write(struct event *event, string_t *str, bool begin)
553667c748977991590854426255e1c34a615f24Timo Sirainen begin ? event->parent : stats_event_get_parent(event);
5478609e31a7665ee108ded988a309673f221aa1Timo Sirainen /* FIXME: we could use create-timestamp of the events to figure out
5478609e31a7665ee108ded988a309673f221aa1Timo Sirainen whether to use BEGIN or to just merge the categories and fields
5fe5ea74285e2fc0fbf7568c53f251aa894650fbTimo Sirainen to the same EVENT. If the parent's timestamp is the same as ours,
5fe5ea74285e2fc0fbf7568c53f251aa894650fbTimo Sirainen don't bother using BEGIN for parent. */
5fe5ea74285e2fc0fbf7568c53f251aa894650fbTimo Sirainen str_printfa(str, "BEGIN\t%"PRIu64"\t", event->id);
5fe5ea74285e2fc0fbf7568c53f251aa894650fbTimo Sirainenstats_client_send_event(struct stats_client *client, struct event *event)
5fe5ea74285e2fc0fbf7568c53f251aa894650fbTimo Sirainen if (!client->handshaked || !event_filter_match(client->filter, event))
5fe5ea74285e2fc0fbf7568c53f251aa894650fbTimo Sirainen o_stream_nsend(client->conn.output, str_data(str), str_len(str));
return TRUE;
return TRUE;
switch (type) {
case EVENT_CALLBACK_TYPE_FREE:
return TRUE;
static void stats_global_init(void)
static void stats_global_deinit(void)
unsigned int i, count;
for (i = 0; i < count; i++)
struct stats_client *
return client;