Synopsis:
<Plugin write_tsdb>
+ DNS_Cache_TTL 60
<Node "example">
Host "tsd-1.my.domain"
Port "4242"
</Plugin>
The configuration consists of one or more E<lt>B<Node>E<nbsp>I<Name>E<gt>
-blocks. Inside the B<Node> blocks, the following options are recognized:
+blocks and global directives.
+
+Global directives are:
+
+=over 4
+
+=item B<DNS_Cache_TTL> I<ttl>
+
+When Collectd connects to a TSDB node, it will request the DNS. This can become
+a problem is the TSDN node is unavailable or badly configured because Collected
+will request DNS in order to reconnect for every metric, which can flood your DNS.
+So you can cache the last value for C<ttl> seconds (default: 60s).
+
+=back
+
+Inside the B<Node> blocks, the following options are recognized:
=over 4
* Private variables
*/
struct wt_callback {
+ struct addrinfo *sock_info;
+ cdtime_t sock_info_last_update;
int sock_fd;
char *node;
pthread_mutex_t send_lock;
};
+static cdtime_t dnsttl = TIME_T_TO_CDTIME_T_STATIC(60);
+
/*
* Functions
*/
}
static int wt_callback_init(struct wt_callback *cb) {
- struct addrinfo *ai_list;
int status;
+ cdtime_t now;
const char *node = cb->node ? cb->node : WT_DEFAULT_NODE;
const char *service = cb->service ? cb->service : WT_DEFAULT_SERVICE;
if (cb->sock_fd > 0)
return 0;
- struct addrinfo ai_hints = {.ai_family = AF_UNSPEC,
- .ai_flags = AI_ADDRCONFIG,
- .ai_socktype = SOCK_STREAM};
+ now = cdtime();
+ if ((cb->sock_info_last_update + dnsttl) < now) {
+ if (cb->sock_info) {
+ freeaddrinfo(cb->sock_info);
+ cb->sock_info = NULL;
+ }
+ }
- status = getaddrinfo(node, service, &ai_hints, &ai_list);
- if (status != 0) {
- ERROR("write_tsdb plugin: getaddrinfo (%s, %s) failed: %s", node, service,
- gai_strerror(status));
- return -1;
+ if (NULL == cb->sock_info) {
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG,
+ .ai_socktype = SOCK_STREAM,
+ };
+
+ if ((cb->sock_info_last_update + dnsttl) >= now) {
+ DEBUG("write_tsdb plugin: too many getaddrinfo (%s, %s) failures", node,
+ service);
+ return (-1);
+ }
+
+ cb->sock_info_last_update = now;
+ status = getaddrinfo(node, service, &ai_hints, &(cb->sock_info));
+ if (status != 0) {
+ if (cb->sock_info) {
+ freeaddrinfo(cb->sock_info);
+ cb->sock_info = NULL;
+ }
+ if (cb->connect_failed_log_enabled) {
+ ERROR("write_tsdb plugin: getaddrinfo (%s, %s) failed: %s", node,
+ service, gai_strerror(status));
+ cb->connect_failed_log_enabled = 0;
+ }
+ return -1;
+ }
}
- assert(ai_list != NULL);
- for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL;
+ assert(cb->sock_info != NULL);
+ for (struct addrinfo *ai_ptr = cb->sock_info; ai_ptr != NULL;
ai_ptr = ai_ptr->ai_next) {
cb->sock_fd =
socket(ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
break;
}
- freeaddrinfo(ai_list);
-
if (cb->sock_fd < 0) {
char errbuf[1024];
ERROR("write_tsdb plugin: Connecting to %s:%s failed. "
return -1;
}
cb->sock_fd = -1;
- cb->node = NULL;
- cb->service = NULL;
- cb->host_tags = NULL;
- cb->store_rates = 0;
pthread_mutex_init(&cb->send_lock, NULL);
if (strcasecmp("Node", child->key) == 0)
wt_config_tsd(child);
- else {
+ if (strcasecmp("DNS_Cache_TTL", child->key) == 0) {
+ int ttl;
+ cf_util_get_int(child, &ttl);
+ dnsttl = TIME_T_TO_CDTIME_T(ttl);
+ } else {
ERROR("write_tsdb plugin: Invalid configuration "
"option: %s.",
child->key);