From: Florian Forster Date: Fri, 4 Dec 2015 10:57:59 +0000 (+0100) Subject: Merge branch 'pr/846' X-Git-Tag: collectd-5.6.0~529 X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=7c702e464f9faf954c320ec5b87c4755083d82bd;hp=aa958d2ad30d29553e489bc727254a8eedb4ea17;p=collectd.git Merge branch 'pr/846' --- diff --git a/src/collectd.conf.in b/src/collectd.conf.in index 63bdb23b..eb230235 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -1348,6 +1348,7 @@ # Host "localhost" # Port "2003" # Protocol "tcp" +# ReconnectInterval 0 # LogSendErrors true # Prefix "collectd" # Postfix "collectd" diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index 9e2f6529..7c5a3c0c 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -7277,6 +7277,14 @@ Service name or port number to connect to. Defaults to C<2003>. Protocol to use when connecting to I. Defaults to C. +=item B I + +When set to non-zero, forces the connection to the Graphite backend to be +closed and re-opend periodically. This behavior is desirable in environments +where the connection to the Graphite backend is done through load balancers, +for example. When set to zero, the default, the connetion is kept open for as +long as possible. + =item B B|B If set to B (the default), logs errors when sending data to I. diff --git a/src/write_graphite.c b/src/write_graphite.c index 7fc9eb9f..0702a6ea 100644 --- a/src/write_graphite.c +++ b/src/write_graphite.c @@ -94,8 +94,36 @@ struct wg_callback pthread_mutex_t send_lock; c_complain_t init_complaint; cdtime_t last_connect_time; + + /* Force reconnect useful for load balanced environments */ + cdtime_t last_reconnect_time; + cdtime_t reconnect_interval; + _Bool reconnect_interval_reached; }; +/* wg_force_reconnect_check closes cb->sock_fd when it was open for longer + * than cb->reconnect_interval. Must hold cb->send_lock when calling. */ +static void wg_force_reconnect_check (struct wg_callback *cb) +{ + cdtime_t now; + + if (cb->reconnect_interval == 0) + return; + + /* check if address changes if addr_timeout */ + now = cdtime (); + if ((now - cb->last_reconnect_time) < cb->reconnect_interval) + return; + + /* here we should close connection on next */ + close (cb->sock_fd); + cb->sock_fd = -1; + cb->last_reconnect_time = now; + cb->reconnect_interval_reached = 1; + + INFO ("write_graphite plugin: Connection closed after %.3f seconds.", + CDTIME_T_TO_DOUBLE (now - cb->last_reconnect_time)); +} /* * Functions @@ -250,7 +278,13 @@ static int wg_callback_init (struct wg_callback *cb) cb->node, cb->service, cb->protocol); } - wg_reset_buffer (cb); + /* wg_force_reconnect_check does not flush the buffer before closing a + * sending socket, so only call wg_reset_buffer() if the socket was closed + * for a different reason (tracked in cb->reconnect_interval_reached). */ + if (!cb->reconnect_interval_reached || (cb->send_buf_free == 0)) + wg_reset_buffer (cb); + else + cb->reconnect_interval_reached = 0; return (0); } @@ -326,6 +360,8 @@ static int wg_send_message (char const *message, struct wg_callback *cb) pthread_mutex_lock (&cb->send_lock); + wg_force_reconnect_check (cb); + if (cb->sock_fd < 0) { status = wg_callback_init (cb); @@ -462,6 +498,9 @@ static int wg_config_node (oconfig_item_t *ci) cb->node = strdup (WG_DEFAULT_NODE); cb->service = strdup (WG_DEFAULT_SERVICE); cb->protocol = strdup (WG_DEFAULT_PROTOCOL); + cb->last_reconnect_time = cdtime(); + cb->reconnect_interval = 0; + cb->reconnect_interval_reached = 0; cb->log_send_errors = WG_DEFAULT_LOG_SEND_ERRORS; cb->prefix = NULL; cb->postfix = NULL; @@ -502,6 +541,8 @@ static int wg_config_node (oconfig_item_t *ci) status = -1; } } + else if (strcasecmp ("ReconnectInterval", child->key) == 0) + cf_util_get_cdtime (child, &cb->reconnect_interval); else if (strcasecmp ("LogSendErrors", child->key) == 0) cf_util_get_boolean (child, &cb->log_send_errors); else if (strcasecmp ("Prefix", child->key) == 0)