* collectd - src/write_http.c
* Copyright (C) 2009 Paul Sadauskas
* Copyright (C) 2009 Doug MacEachern
- * Copyright (C) 2007-2009 Florian octo Forster
+ * Copyright (C) 2007-2014 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
- * Florian octo Forster <octo at verplant.org>
+ * Florian octo Forster <octo at collectd.org>
* Doug MacEachern <dougm@hyperic.com>
* Paul Sadauskas <psadauskas@gmail.com>
**/
#include "plugin.h"
#include "common.h"
#include "utils_cache.h"
-#include "utils_parse_option.h"
#include "utils_format_json.h"
#if HAVE_PTHREAD_H
#include <curl/curl.h>
+#ifndef WRITE_HTTP_DEFAULT_BUFFER_SIZE
+# define WRITE_HTTP_DEFAULT_BUFFER_SIZE 4096
+#endif
+
+#define WH_DEFAULT_LOW_LIMIT_BYTES_PER_SEC 100
/*
* Private variables
*/
char *clientkeypass;
long sslversion;
_Bool store_rates;
+ _Bool abort_on_slow;
+ int low_limit_bytes;
+ time_t interval;
#define WH_FORMAT_COMMAND 0
#define WH_FORMAT_JSON 1
CURL *curl;
char curl_errbuf[CURL_ERROR_SIZE];
- char send_buffer[4096];
+ char *send_buffer;
+ size_t send_buffer_size;
size_t send_buffer_free;
size_t send_buffer_fill;
cdtime_t send_buffer_init_time;
static void wh_reset_buffer (wh_callback_t *cb) /* {{{ */
{
- memset (cb->send_buffer, 0, sizeof (cb->send_buffer));
- cb->send_buffer_free = sizeof (cb->send_buffer);
+ memset (cb->send_buffer, 0, cb->send_buffer_size);
+ cb->send_buffer_free = cb->send_buffer_size;
cb->send_buffer_fill = 0;
cb->send_buffer_init_time = cdtime ();
return (-1);
}
+ if(cb->abort_on_slow && cb->interval > 0)
+ {
+ curl_easy_setopt(cb->curl, CURLOPT_LOW_SPEED_LIMIT, (cb->low_limit_bytes?cb->low_limit_bytes:WH_DEFAULT_LOW_LIMIT_BYTES_PER_SEC));
+ curl_easy_setopt(cb->curl, CURLOPT_LOW_SPEED_TIME, cb->interval);
+ }
+
curl_easy_setopt (cb->curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt (cb->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
wh_flush_nolock (/* timeout = */ 0, cb);
- curl_easy_cleanup (cb->curl);
+ if (cb->curl != NULL)
+ {
+ curl_easy_cleanup (cb->curl);
+ cb->curl = NULL;
+ }
sfree (cb->location);
sfree (cb->user);
sfree (cb->pass);
sfree (cb->clientkey);
sfree (cb->clientcert);
sfree (cb->clientkeypass);
+ sfree (cb->send_buffer);
sfree (cb);
} /* }}} void wh_callback_free */
if (cb->curl == NULL)
{
+ cb->interval = CDTIME_T_TO_TIME_T(vl->interval);
status = wh_callback_init (cb);
if (status != 0)
{
DEBUG ("write_http plugin: <%s> buffer %zu/%zu (%g%%) \"%s\"",
cb->location,
- cb->send_buffer_fill, sizeof (cb->send_buffer),
- 100.0 * ((double) cb->send_buffer_fill) / ((double) sizeof (cb->send_buffer)),
+ cb->send_buffer_fill, cb->send_buffer_size,
+ 100.0 * ((double) cb->send_buffer_fill) / ((double) cb->send_buffer_size),
command);
/* Check if we have enough space for this command. */
wh_callback_t *cb)
{
int status;
-
+
pthread_mutex_lock (&cb->send_lock);
if (cb->curl == NULL)
{
+ cb->interval = CDTIME_T_TO_TIME_T(vl->interval);
+
status = wh_callback_init (cb);
if (status != 0)
{
DEBUG ("write_http plugin: <%s> buffer %zu/%zu (%g%%)",
cb->location,
- cb->send_buffer_fill, sizeof (cb->send_buffer),
- 100.0 * ((double) cb->send_buffer_fill) / ((double) sizeof (cb->send_buffer)));
+ cb->send_buffer_fill, cb->send_buffer_size,
+ 100.0 * ((double) cb->send_buffer_fill) / ((double) cb->send_buffer_size));
/* Check if we have enough space for this command. */
pthread_mutex_unlock (&cb->send_lock);
static int wh_config_url (oconfig_item_t *ci) /* {{{ */
{
wh_callback_t *cb;
+ int buffer_size = 0;
user_data_t user_data;
int i;
cb->verify_host = 1;
cb->format = WH_FORMAT_COMMAND;
cb->sslversion = CURL_SSLVERSION_DEFAULT;
+ cb->low_limit_bytes = WH_DEFAULT_LOW_LIMIT_BYTES_PER_SEC;
pthread_mutex_init (&cb->send_lock, /* attr = */ NULL);
config_set_format (cb, child);
else if (strcasecmp ("StoreRates", child->key) == 0)
cf_util_get_boolean (child, &cb->store_rates);
+ else if (strcasecmp ("BufferSize", child->key) == 0)
+ cf_util_get_int (child, &buffer_size);
+ else if (strcasecmp ("LowSpeedLimit", child->key) == 0)
+ cf_util_get_boolean (child,&cb->abort_on_slow);
+ else if (strcasecmp ("LowLimitBytesPerSec", child->key) == 0)
+ cf_util_get_int (child, &cb->low_limit_bytes);
else
{
ERROR ("write_http plugin: Invalid configuration "
}
}
+ if(cb->abort_on_slow)
+ {
+ cb->interval = CDTIME_T_TO_TIME_T(cf_get_default_interval ());
+ }
+
+ /* Determine send_buffer_size. */
+ cb->send_buffer_size = WRITE_HTTP_DEFAULT_BUFFER_SIZE;
+ if (buffer_size >= 1024)
+ cb->send_buffer_size = (size_t) buffer_size;
+ else if (buffer_size != 0)
+ ERROR ("write_http plugin: Ignoring invalid BufferSize setting (%d).",
+ buffer_size);
+
+ /* Allocate the buffer. */
+ cb->send_buffer = malloc (cb->send_buffer_size);
+ if (cb->send_buffer == NULL)
+ {
+ ERROR ("write_http plugin: malloc(%zu) failed.", cb->send_buffer_size);
+ wh_callback_free (cb);
+ return (-1);
+ }
+ /* Nulls the buffer and sets ..._free and ..._fill. */
+ wh_reset_buffer (cb);
+
DEBUG ("write_http: Registering write callback with URL %s",
cb->location);
return (0);
} /* }}} int wh_config */
+static int wh_init (void) /* {{{ */
+{
+ /* Call this while collectd is still single-threaded to avoid
+ * initialization issues in libgcrypt. */
+ curl_global_init (CURL_GLOBAL_SSL);
+ return (0);
+} /* }}} int wh_init */
+
void module_register (void) /* {{{ */
{
plugin_register_complex_config ("write_http", wh_config);
+ plugin_register_init ("write_http", wh_init);
} /* }}} void module_register */
/* vim: set fdm=marker sw=8 ts=8 tw=78 et : */