if (st == NULL) {
ERROR("apache plugin: apache_curl_callback: "
"user_data pointer is NULL.");
- return (0);
+ return 0;
}
if (len == 0)
- return (len);
+ return len;
if ((st->apache_buffer_fill + len) >= st->apache_buffer_size) {
char *temp;
temp = realloc(st->apache_buffer, st->apache_buffer_fill + len + 1);
if (temp == NULL) {
ERROR("apache plugin: realloc failed.");
- return (0);
+ return 0;
}
st->apache_buffer = temp;
st->apache_buffer_size = st->apache_buffer_fill + len + 1;
st->apache_buffer_fill += len;
st->apache_buffer[st->apache_buffer_fill] = 0;
- return (len);
+ return len;
} /* int apache_curl_callback */
static size_t apache_header_callback(void *buf, size_t size, size_t nmemb,
if (st == NULL) {
ERROR("apache plugin: apache_header_callback: "
"user_data pointer is NULL.");
- return (0);
+ return 0;
}
if (len == 0)
- return (len);
+ return len;
/* look for the Server header */
if (strncasecmp(buf, "Server: ", strlen("Server: ")) != 0)
- return (len);
+ return len;
if (strstr(buf, "Apache") != NULL)
st->server_type = APACHE;
NOTICE("apache plugin: Unknown server software: %s", hdr);
}
- return (len);
+ return len;
} /* apache_header_callback */
/* Configuration handling functiions
st = calloc(1, sizeof(*st));
if (st == NULL) {
ERROR("apache plugin: calloc failed.");
- return (-1);
+ return -1;
}
st->timeout = -1;
status = cf_util_get_string(ci, &st->name);
if (status != 0) {
sfree(st);
- return (status);
+ return status;
}
assert(st->name != NULL);
if (status != 0) {
apache_free(st);
- return (-1);
+ return -1;
}
- return (0);
+ return 0;
} /* int config_add */
static int config(oconfig_item_t *ci) {
child->key);
} /* for (ci->children) */
- return (status);
+ return status;
} /* int config */
/* initialize curl for each host */
if ((st->curl = curl_easy_init()) == NULL) {
ERROR("apache plugin: init_host: `curl_easy_init' failed.");
- return (-1);
+ return -1;
}
curl_easy_setopt(st->curl, CURLOPT_NOSIGNAL, 1L);
"truncated.");
curl_easy_cleanup(st->curl);
st->curl = NULL;
- return (-1);
+ return -1;
}
curl_easy_setopt(st->curl, CURLOPT_USERPWD, credentials);
#endif
}
- curl_easy_setopt(st->curl, CURLOPT_URL, st->url);
curl_easy_setopt(st->curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(st->curl, CURLOPT_MAXREDIRS, 50L);
(long)CDTIME_T_TO_MS(plugin_get_interval()));
#endif
- return (0);
+ return 0;
} /* }}} int init_host */
static void submit_value(const char *type, const char *type_instance,
if (st->curl == NULL) {
status = init_host(st);
if (status != 0)
- return (-1);
+ return -1;
}
assert(st->curl != NULL);
st->apache_buffer_fill = 0;
+
+ curl_easy_setopt(st->curl, CURLOPT_URL, st->url);
+
if (curl_easy_perform(st->curl) != CURLE_OK) {
ERROR("apache: curl_easy_perform failed: %s", st->apache_curl_error);
- return (-1);
+ return -1;
}
/* fallback - server_type to apache if not set at this time */
st->apache_buffer_fill = 0;
- return (0);
+ return 0;
} /* }}} int apache_read_host */
static int apache_init(void) /* {{{ */
/* Call this while collectd is still single-threaded to avoid
* initialization issues in libgcrypt. */
curl_global_init(CURL_GLOBAL_SSL);
- return (0);
+ return 0;
} /* }}} int apache_init */
void module_register(void) {
plugin_register_complex_config("apache", config);
plugin_register_init("apache", apache_init);
} /* void module_register */
-
-/* vim: set sw=8 noet fdm=marker : */
sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
plugin_dispatch_values(&vl);
- return (0);
+ return 0;
} /* }}} int ascent_submit_gauge */
static size_t ascent_curl_callback(void *buf, size_t size,
size_t len = size * nmemb;
if (len == 0)
- return (len);
+ return len;
if ((ascent_buffer_fill + len) >= ascent_buffer_size) {
char *temp;
temp = realloc(ascent_buffer, ascent_buffer_fill + len + 1);
if (temp == NULL) {
ERROR("ascent plugin: realloc failed.");
- return (0);
+ return 0;
}
ascent_buffer = temp;
ascent_buffer_size = ascent_buffer_fill + len + 1;
ascent_buffer_fill += len;
ascent_buffer[ascent_buffer_fill] = 0;
- return (len);
+ return len;
} /* }}} size_t ascent_curl_callback */
static int ascent_submit_players(player_stats_t *ps) /* {{{ */
value = ((double)ps->latency_sum) / (1000.0 * ((double)ps->latency_num));
ascent_submit_gauge(NULL, "latency", "average", value);
- return (0);
+ return 0;
} /* }}} int ascent_submit_players */
static int ascent_account_player(player_stats_t *ps, /* {{{ */
ps->latency_num++;
}
- return (0);
+ return 0;
} /* }}} int ascent_account_player */
static int ascent_xml_submit_gauge(xmlDoc *doc, xmlNode *node, /* {{{ */
if (str_ptr == NULL) {
ERROR(
"ascent plugin: ascent_xml_submit_gauge: xmlNodeListGetString failed.");
- return (-1);
+ return -1;
}
if (strcasecmp("N/A", str_ptr) == 0)
if (str_ptr == end_ptr) {
xmlFree(str_ptr);
ERROR("ascent plugin: ascent_xml_submit_gauge: strtod failed.");
- return (-1);
+ return -1;
}
}
xmlFree(str_ptr);
- return (ascent_submit_gauge(plugin_instance, type, type_instance, value));
+ return ascent_submit_gauge(plugin_instance, type, type_instance, value);
} /* }}} int ascent_xml_submit_gauge */
static int ascent_xml_read_int(xmlDoc *doc, xmlNode *node, /* {{{ */
str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (str_ptr == NULL) {
ERROR("ascent plugin: ascent_xml_read_int: xmlNodeListGetString failed.");
- return (-1);
+ return -1;
}
if (strcasecmp("N/A", str_ptr) == 0)
if (str_ptr == end_ptr) {
xmlFree(str_ptr);
ERROR("ascent plugin: ascent_xml_read_int: strtol failed.");
- return (-1);
+ return -1;
}
}
xmlFree(str_ptr);
*ret_value = value;
- return (0);
+ return 0;
} /* }}} int ascent_xml_read_int */
static int ascent_xml_sessions_plr(xmlDoc *doc, xmlNode *node, /* {{{ */
}
} /* for (child) */
- return (0);
+ return 0;
} /* }}} int ascent_xml_sessions_plr */
static int ascent_xml_sessions(xmlDoc *doc, xmlNode *node) /* {{{ */
ascent_submit_players(&ps);
- return (0);
+ return 0;
} /* }}} int ascent_xml_sessions */
static int ascent_xml_status(xmlDoc *doc, xmlNode *node) /* {{{ */
}
} /* for (child) */
- return (0);
+ return 0;
} /* }}} int ascent_xml_status */
static int ascent_xml(const char *data) /* {{{ */
#endif
if (doc == NULL) {
ERROR("ascent plugin: xmlParseMemory failed.");
- return (-1);
+ return -1;
}
cur = xmlDocGetRootElement(doc);
if (cur == NULL) {
ERROR("ascent plugin: XML document is empty.");
xmlFreeDoc(doc);
- return (-1);
+ return -1;
}
if (xmlStrcmp((const xmlChar *)"serverpage", cur->name) != 0) {
ERROR("ascent plugin: XML root element is not \"serverpage\".");
xmlFreeDoc(doc);
- return (-1);
+ return -1;
}
for (xmlNode *child = cur->xmlChildrenNode; child != NULL;
} /* for (child) */
xmlFreeDoc(doc);
- return (0);
+ return 0;
} /* }}} int ascent_xml */
static int config_set(char **var, const char *value) /* {{{ */
}
if ((*var = strdup(value)) == NULL)
- return (1);
+ return 1;
else
- return (0);
+ return 0;
} /* }}} int config_set */
static int ascent_config(const char *key, const char *value) /* {{{ */
{
if (strcasecmp(key, "URL") == 0)
- return (config_set(&url, value));
+ return config_set(&url, value);
else if (strcasecmp(key, "User") == 0)
- return (config_set(&user, value));
+ return config_set(&user, value);
else if (strcasecmp(key, "Password") == 0)
- return (config_set(&pass, value));
+ return config_set(&pass, value);
else if (strcasecmp(key, "VerifyPeer") == 0)
- return (config_set(&verify_peer, value));
+ return config_set(&verify_peer, value);
else if (strcasecmp(key, "VerifyHost") == 0)
- return (config_set(&verify_host, value));
+ return config_set(&verify_host, value);
else if (strcasecmp(key, "CACert") == 0)
- return (config_set(&cacert, value));
+ return config_set(&cacert, value);
else if (strcasecmp(key, "Timeout") == 0)
- return (config_set(&timeout, value));
+ return config_set(&timeout, value);
else
- return (-1);
+ return -1;
} /* }}} int ascent_config */
static int ascent_init(void) /* {{{ */
if (url == NULL) {
WARNING("ascent plugin: ascent_init: No URL configured, "
"returning an error.");
- return (-1);
+ return -1;
}
if (curl != NULL) {
if ((curl = curl_easy_init()) == NULL) {
ERROR("ascent plugin: ascent_init: curl_easy_init failed.");
- return (-1);
+ return -1;
}
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
if ((status < 0) || ((size_t)status >= sizeof(credentials))) {
ERROR("ascent plugin: ascent_init: Returning an error because the "
"credentials have been truncated.");
- return (-1);
+ return -1;
}
curl_easy_setopt(curl, CURLOPT_USERPWD, credentials);
#endif
}
- curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
(long)CDTIME_T_TO_MS(plugin_get_interval()));
#endif
- return (0);
+ return 0;
} /* }}} int ascent_init */
static int ascent_read(void) /* {{{ */
if (curl == NULL) {
ERROR("ascent plugin: I don't have a CURL object.");
- return (-1);
+ return -1;
}
if (url == NULL) {
ERROR("ascent plugin: No URL has been configured.");
- return (-1);
+ return -1;
}
ascent_buffer_fill = 0;
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+
if (curl_easy_perform(curl) != CURLE_OK) {
ERROR("ascent plugin: curl_easy_perform failed: %s", ascent_curl_error);
- return (-1);
+ return -1;
}
status = ascent_xml(ascent_buffer);
if (status != 0)
- return (-1);
+ return -1;
else
- return (0);
+ return 0;
} /* }}} int ascent_read */
void module_register(void) {
plugin_register_init("ascent", ascent_init);
plugin_register_read("ascent", ascent_read);
} /* void module_register */
-
-/* vim: set sw=2 sts=2 ts=8 et fdm=marker : */
size_t len = size * nmemb;
if (len == 0)
- return (len);
+ return len;
if ((bind_buffer_fill + len) >= bind_buffer_size) {
char *temp;
temp = realloc(bind_buffer, bind_buffer_fill + len + 1);
if (temp == NULL) {
ERROR("bind plugin: realloc failed.");
- return (0);
+ return 0;
}
bind_buffer = temp;
bind_buffer_size = bind_buffer_fill + len + 1;
bind_buffer_fill += len;
bind_buffer[bind_buffer_fill] = 0;
- return (len);
+ return len;
} /* }}} size_t bind_curl_callback */
/*
translation_table_ptr_t *table = (translation_table_ptr_t *)user_data;
if (table == NULL)
- return (-1);
+ return -1;
for (size_t i = 0; i < table->table_length; i++) {
if (strcmp(table->table[i].xml_name, name) != 0)
break;
}
- return (0);
+ return 0;
} /* }}} int bind_xml_table_callback */
/*
list_info_ptr_t *list_info = (list_info_ptr_t *)user_data;
if (list_info == NULL)
- return (-1);
+ return -1;
submit(current_time, list_info->plugin_instance, list_info->type,
/* type instance = */ name, value);
- return (0);
+ return 0;
} /* }}} int bind_xml_list_callback */
static int bind_xml_read_derive(xmlDoc *doc, xmlNode *node, /* {{{ */
str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (str_ptr == NULL) {
ERROR("bind plugin: bind_xml_read_derive: xmlNodeListGetString failed.");
- return (-1);
+ return -1;
}
status = parse_value(str_ptr, &value, DS_TYPE_DERIVE);
ERROR("bind plugin: Parsing string \"%s\" to derive value failed.",
str_ptr);
xmlFree(str_ptr);
- return (-1);
+ return -1;
}
xmlFree(str_ptr);
*ret_value = value.derive;
- return (0);
+ return 0;
} /* }}} int bind_xml_read_derive */
static int bind_xml_read_gauge(xmlDoc *doc, xmlNode *node, /* {{{ */
str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (str_ptr == NULL) {
ERROR("bind plugin: bind_xml_read_gauge: xmlNodeListGetString failed.");
- return (-1);
+ return -1;
}
errno = 0;
ERROR("bind plugin: bind_xml_read_gauge: strtod failed with overflow.");
else
ERROR("bind plugin: bind_xml_read_gauge: strtod failed.");
- return (-1);
+ return -1;
}
*ret_value = (gauge_t)value;
- return (0);
+ return 0;
} /* }}} int bind_xml_read_gauge */
static int bind_xml_read_timestamp(const char *xpath_expression, /* {{{ */
if (xpathObj == NULL) {
ERROR("bind plugin: Unable to evaluate XPath expression `%s'.",
xpath_expression);
- return (-1);
+ return -1;
}
if ((xpathObj->nodesetval == NULL) || (xpathObj->nodesetval->nodeNr < 1)) {
xmlXPathFreeObject(xpathObj);
- return (-1);
+ return -1;
}
if (xpathObj->nodesetval->nodeNr != 1) {
ERROR("bind plugin: bind_xml_read_timestamp: "
"node->xmlChildrenNode == NULL");
xmlXPathFreeObject(xpathObj);
- return (-1);
+ return -1;
}
str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (str_ptr == NULL) {
ERROR("bind plugin: bind_xml_read_timestamp: xmlNodeListGetString failed.");
xmlXPathFreeObject(xpathObj);
- return (-1);
+ return -1;
}
tmp = strptime(str_ptr, "%Y-%m-%dT%T", &tm);
if (tmp == NULL) {
ERROR("bind plugin: bind_xml_read_timestamp: strptime failed.");
xmlXPathFreeObject(xpathObj);
- return (-1);
+ return -1;
}
#if HAVE_TIMEGM
char errbuf[1024];
ERROR("bind plugin: timegm() failed: %s",
sstrerror(errno, errbuf, sizeof(errbuf)));
- return (-1);
+ return -1;
}
*ret_value = t;
#else
char errbuf[1024];
ERROR("bind plugin: mktime() failed: %s",
sstrerror(errno, errbuf, sizeof(errbuf)));
- return (-1);
+ return -1;
}
/* mktime assumes that tm is local time. Luckily, it also sets timezone to
* the offset used for the conversion, and we undo the conversion to convert
#endif
xmlXPathFreeObject(xpathObj);
- return (0);
+ return 0;
} /* }}} int bind_xml_read_timestamp */
/*
if (xpathObj == NULL) {
ERROR("bind plugin: Unable to evaluate XPath expression `%s'.",
xpath_expression);
- return (-1);
+ return -1;
}
num_entries = 0;
xmlXPathFreeObject(xpathObj);
- return (0);
+ return 0;
} /* }}} int bind_parse_generic_name_value */
/*
if (xpathObj == NULL) {
ERROR("bind plugin: Unable to evaluate XPath expression `%s'.",
xpath_expression);
- return (-1);
+ return -1;
}
num_entries = 0;
xmlXPathFreeObject(xpathObj);
- return (0);
+ return 0;
} /* }}} int bind_parse_generic_value_list */
/*
if (xpathObj == NULL) {
ERROR("bind plugin: Unable to evaluate XPath expression `%s'.",
xpath_expression);
- return (-1);
+ return -1;
}
num_entries = 0;
xmlXPathFreeObject(xpathObj);
- return (0);
+ return 0;
} /* }}} int bind_parse_generic_name_attr_value_list */
static int bind_xml_stats_handle_zone(int version, xmlDoc *doc, /* {{{ */
path_obj = xmlXPathEvalExpression(BAD_CAST "name", path_ctx);
if (path_obj == NULL) {
ERROR("bind plugin: xmlXPathEvalExpression failed.");
- return (-1);
+ return -1;
}
for (int i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr);
if (zone_name == NULL) {
ERROR("bind plugin: Could not determine zone name.");
- return (-1);
+ return -1;
}
for (j = 0; j < view->zones_num; j++) {
zone_name = NULL;
if (j >= view->zones_num)
- return (0);
+ return 0;
zone_name = view->zones[j];
}
} /* }}} */
- return (0);
+ return 0;
} /* }}} int bind_xml_stats_handle_zone */
static int bind_xml_stats_search_zones(int version, xmlDoc *doc, /* {{{ */
zone_path_context = xmlXPathNewContext(doc);
if (zone_path_context == NULL) {
ERROR("bind plugin: xmlXPathNewContext failed.");
- return (-1);
+ return -1;
}
zone_nodes = xmlXPathEvalExpression(BAD_CAST "zones/zone", path_ctx);
if (zone_nodes == NULL) {
ERROR("bind plugin: Cannot find any <view> tags.");
xmlXPathFreeContext(zone_path_context);
- return (-1);
+ return -1;
}
for (int i = 0; i < zone_nodes->nodesetval->nodeNr; i++) {
xmlXPathFreeObject(zone_nodes);
xmlXPathFreeContext(zone_path_context);
- return (0);
+ return 0;
} /* }}} int bind_xml_stats_search_zones */
static int bind_xml_stats_handle_view(int version, xmlDoc *doc, /* {{{ */
if (view_name == NULL) {
ERROR("bind plugin: Could not determine view name.");
- return (-1);
+ return -1;
}
for (j = 0; j < views_num; j++) {
path_obj = xmlXPathEvalExpression(BAD_CAST "name", path_ctx);
if (path_obj == NULL) {
ERROR("bind plugin: xmlXPathEvalExpression failed.");
- return (-1);
+ return -1;
}
for (int i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr);
if (view_name == NULL) {
ERROR("bind plugin: Could not determine view name.");
xmlXPathFreeObject(path_obj);
- return (-1);
+ return -1;
}
for (j = 0; j < views_num; j++) {
}
if (j >= views_num)
- return (0);
+ return 0;
view = views + j;
bind_xml_stats_search_zones(version, doc, path_ctx, node, view,
current_time);
- return (0);
+ return 0;
} /* }}} int bind_xml_stats_handle_view */
static int bind_xml_stats_search_views(int version, xmlDoc *doc, /* {{{ */
view_path_context = xmlXPathNewContext(doc);
if (view_path_context == NULL) {
ERROR("bind plugin: xmlXPathNewContext failed.");
- return (-1);
+ return -1;
}
view_nodes = xmlXPathEvalExpression(BAD_CAST "views/view", xpathCtx);
if (view_nodes == NULL) {
ERROR("bind plugin: Cannot find any <view> tags.");
xmlXPathFreeContext(view_path_context);
- return (-1);
+ return -1;
}
for (int i = 0; i < view_nodes->nodesetval->nodeNr; i++) {
xmlXPathFreeObject(view_nodes);
xmlXPathFreeContext(view_path_context);
- return (0);
+ return 0;
} /* }}} int bind_xml_stats_search_views */
static void bind_xml_stats_v3(xmlDoc *doc, /* {{{ */
¤t_time);
if (status != 0) {
ERROR("bind plugin: Reading `server/current-time' failed.");
- return (-1);
+ return -1;
}
DEBUG("bind plugin: Current server time is %i.", (int)current_time);
doc = xmlParseMemory(data, strlen(data));
if (doc == NULL) {
ERROR("bind plugin: xmlParseMemory failed.");
- return (-1);
+ return -1;
}
xpathCtx = xmlXPathNewContext(doc);
if (xpathCtx == NULL) {
ERROR("bind plugin: xmlXPathNewContext failed.");
xmlFreeDoc(doc);
- return (-1);
+ return -1;
}
//
xmlXPathFreeContext(xpathCtx);
xmlFreeDoc(doc);
- return (ret);
+ return ret;
}
//
ERROR("bind plugin: Cannot find the <statistics> tag.");
xmlXPathFreeContext(xpathCtx);
xmlFreeDoc(doc);
- return (-1);
+ return -1;
} else if (xpathObj->nodesetval == NULL) {
ERROR("bind plugin: xmlXPathEvalExpression failed.");
xmlXPathFreeObject(xpathObj);
xmlXPathFreeContext(xpathCtx);
xmlFreeDoc(doc);
- return (-1);
+ return -1;
}
for (int i = 0; i < xpathObj->nodesetval->nodeNr; i++) {
xmlXPathFreeContext(xpathCtx);
xmlFreeDoc(doc);
- return (ret);
+ return ret;
} /* }}} int bind_xml */
static int bind_config_set_bool(const char *name, int *var, /* {{{ */
WARNING("bind plugin: The `%s' option needs "
"exactly one boolean argument.",
name);
- return (-1);
+ return -1;
}
if (ci->values[0].value.boolean)
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("bind plugin: The `Zone' option needs "
"exactly one string argument.");
- return (-1);
+ return -1;
}
tmp = realloc(view->zones, sizeof(char *) * (view->zones_num + 1));
if (tmp == NULL) {
ERROR("bind plugin: realloc failed.");
- return (-1);
+ return -1;
}
view->zones = tmp;
view->zones[view->zones_num] = strdup(ci->values[0].value.string);
if (view->zones[view->zones_num] == NULL) {
ERROR("bind plugin: strdup failed.");
- return (-1);
+ return -1;
}
view->zones_num++;
- return (0);
+ return 0;
} /* }}} int bind_config_add_view_zone */
static int bind_config_add_view(oconfig_item_t *ci) /* {{{ */
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("bind plugin: `View' blocks need exactly one string argument.");
- return (-1);
+ return -1;
}
tmp = realloc(views, sizeof(*views) * (views_num + 1));
if (tmp == NULL) {
ERROR("bind plugin: realloc failed.");
- return (-1);
+ return -1;
}
views = tmp;
tmp = views + views_num;
if (tmp->name == NULL) {
ERROR("bind plugin: strdup failed.");
sfree(views);
- return (-1);
+ return -1;
}
for (int i = 0; i < ci->children_num; i++) {
} /* for (i = 0; i < ci->children_num; i++) */
views_num++;
- return (0);
+ return 0;
} /* }}} int bind_config_add_view */
static int bind_config(oconfig_item_t *ci) /* {{{ */
(child->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("bind plugin: The `Url' option needs "
"exactly one string argument.");
- return (-1);
+ return -1;
}
sfree(url);
}
}
- return (0);
+ return 0;
} /* }}} int bind_config */
static int bind_init(void) /* {{{ */
{
if (curl != NULL)
- return (0);
+ return 0;
curl = curl_easy_init();
if (curl == NULL) {
ERROR("bind plugin: bind_init: curl_easy_init failed.");
- return (-1);
+ return -1;
}
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, bind_curl_callback);
curl_easy_setopt(curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, bind_curl_error);
- curl_easy_setopt(curl, CURLOPT_URL, (url != NULL) ? url : BIND_DEFAULT_URL);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
#ifdef HAVE_CURLOPT_TIMEOUT_MS
plugin_get_interval()));
#endif
- return (0);
+ return 0;
} /* }}} int bind_init */
static int bind_read(void) /* {{{ */
if (curl == NULL) {
ERROR("bind plugin: I don't have a CURL object.");
- return (-1);
+ return -1;
}
bind_buffer_fill = 0;
+
+ curl_easy_setopt(curl, CURLOPT_URL, (url != NULL) ? url : BIND_DEFAULT_URL);
+
if (curl_easy_perform(curl) != CURLE_OK) {
ERROR("bind plugin: curl_easy_perform failed: %s", bind_curl_error);
- return (-1);
+ return -1;
}
status = bind_xml(bind_buffer);
if (status != 0)
- return (-1);
+ return -1;
else
- return (0);
+ return 0;
} /* }}} int bind_read */
static int bind_shutdown(void) /* {{{ */
curl = NULL;
}
- return (0);
+ return 0;
} /* }}} int bind_shutdown */
void module_register(void) {
plugin_register_read("bind", bind_read);
plugin_register_shutdown("bind", bind_shutdown);
} /* void module_register */
-
-/* vim: set sw=2 sts=2 ts=8 et fdm=marker : */
len = size * nmemb;
if (len == 0)
- return (len);
+ return len;
wp = user_data;
if (wp == NULL)
- return (0);
+ return 0;
if ((wp->buffer_fill + len) >= wp->buffer_size) {
char *temp;
temp = realloc(wp->buffer, temp_size);
if (temp == NULL) {
ERROR("curl plugin: realloc failed.");
- return (0);
+ return 0;
}
wp->buffer = temp;
wp->buffer_size = temp_size;
wp->buffer_fill += len;
wp->buffer[wp->buffer_fill] = 0;
- return (len);
+ return len;
} /* }}} size_t cc_curl_callback */
static void cc_web_match_free(web_match_t *wm) /* {{{ */
struct curl_slist *temp = NULL;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("curl plugin: `%s' needs exactly one string argument.", name);
- return (-1);
+ return -1;
}
temp = curl_slist_append(*dest, ci->values[0].value.string);
if (temp == NULL)
- return (-1);
+ return -1;
*dest = temp;
- return (0);
+ return 0;
} /* }}} int cc_config_append_string */
static int cc_config_add_match_dstype(int *dstype_ret, /* {{{ */
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("curl plugin: `DSType' needs exactly one string argument.");
- return (-1);
+ return -1;
}
if (strncasecmp("Gauge", ci->values[0].value.string, strlen("Gauge")) == 0) {
if (dstype == 0) {
WARNING("curl plugin: `%s' is not a valid argument to `DSType'.",
ci->values[0].value.string);
- return (-1);
+ return -1;
}
*dstype_ret = dstype;
- return (0);
+ return 0;
} /* }}} int cc_config_add_match_dstype */
static int cc_config_add_match(web_page_t *page, /* {{{ */
match = calloc(1, sizeof(*match));
if (match == NULL) {
ERROR("curl plugin: calloc failed.");
- return (-1);
+ return -1;
}
status = 0;
if (status != 0) {
cc_web_match_free(match);
- return (status);
+ return status;
}
match->match =
if (match->match == NULL) {
ERROR("curl plugin: match_create_simple failed.");
cc_web_match_free(match);
- return (-1);
+ return -1;
} else {
web_match_t *prev;
prev->next = match;
}
- return (0);
+ return 0;
} /* }}} int cc_config_add_match */
static int cc_page_init_curl(web_page_t *wp) /* {{{ */
wp->curl = curl_easy_init();
if (wp->curl == NULL) {
ERROR("curl plugin: curl_easy_init failed.");
- return (-1);
+ return -1;
}
curl_easy_setopt(wp->curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(wp->curl, CURLOPT_WRITEDATA, wp);
curl_easy_setopt(wp->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt(wp->curl, CURLOPT_ERRORBUFFER, wp->curl_errbuf);
- curl_easy_setopt(wp->curl, CURLOPT_URL, wp->url);
curl_easy_setopt(wp->curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(wp->curl, CURLOPT_MAXREDIRS, 50L);
wp->credentials = malloc(credentials_size);
if (wp->credentials == NULL) {
ERROR("curl plugin: malloc failed.");
- return (-1);
+ return -1;
}
ssnprintf(wp->credentials, credentials_size, "%s:%s", wp->user,
(long)CDTIME_T_TO_MS(plugin_get_interval()));
#endif
- return (0);
+ return 0;
} /* }}} int cc_page_init_curl */
static int cc_config_add_page(oconfig_item_t *ci) /* {{{ */
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("curl plugin: `Page' blocks need exactly one string argument.");
- return (-1);
+ return -1;
}
page = calloc(1, sizeof(*page));
if (page == NULL) {
ERROR("curl plugin: calloc failed.");
- return (-1);
+ return -1;
}
page->url = NULL;
page->user = NULL;
if (page->instance == NULL) {
ERROR("curl plugin: strdup failed.");
sfree(page);
- return (-1);
+ return -1;
}
/* Process all children */
if (status != 0) {
cc_web_page_free(page);
- return (status);
+ return status;
}
/* Add the new page to the linked list */
prev->next = page;
}
- return (0);
+ return 0;
} /* }}} int cc_config_add_page */
static int cc_config(oconfig_item_t *ci) /* {{{ */
if ((success == 0) && (errors > 0)) {
ERROR("curl plugin: All statements failed.");
- return (-1);
+ return -1;
}
- return (0);
+ return 0;
} /* }}} int cc_config */
static int cc_init(void) /* {{{ */
{
if (pages_g == NULL) {
INFO("curl plugin: No pages have been defined.");
- return (-1);
+ return -1;
}
curl_global_init(CURL_GLOBAL_SSL);
- return (0);
+ return 0;
} /* }}} int cc_init */
static void cc_submit(const web_page_t *wp, const web_match_t *wm, /* {{{ */
start = cdtime();
wp->buffer_fill = 0;
+
+ curl_easy_setopt(wp->curl, CURLOPT_URL, wp->url);
+
status = curl_easy_perform(wp->curl);
if (status != CURLE_OK) {
ERROR("curl plugin: curl_easy_perform failed with status %i: %s", status,
wp->curl_errbuf);
- return (-1);
+ return -1;
}
if (wp->response_time)
match_value_reset(mv);
} /* for (wm = wp->matches; wm != NULL; wm = wm->next) */
- return (0);
+ return 0;
} /* }}} int cc_read_page */
static int cc_read(void) /* {{{ */
for (web_page_t *wp = pages_g; wp != NULL; wp = wp->next)
cc_read_page(wp);
- return (0);
+ return 0;
} /* }}} int cc_read */
static int cc_shutdown(void) /* {{{ */
cc_web_page_free(pages_g);
pages_g = NULL;
- return (0);
+ return 0;
} /* }}} int cc_shutdown */
void module_register(void) {
plugin_register_read("curl", cc_read);
plugin_register_shutdown("curl", cc_shutdown);
} /* void module_register */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
#endif
#define CJ_DEFAULT_HOST "localhost"
-#define CJ_KEY_MAGIC 0x43484b59UL /* CHKY */
-#define CJ_IS_KEY(key) ((key)->magic == CJ_KEY_MAGIC)
#define CJ_ANY "*"
#define COUCH_MIN(x, y) ((x) < (y) ? (x) : (y))
typedef struct cj_key_s cj_key_t;
struct cj_key_s /* {{{ */
{
- unsigned long magic;
char *path;
char *type;
char *instance;
};
/* }}} */
+/* cj_tree_entry_t is a union of either a metric configuration ("key") or a tree
+ * mapping array indexes / map keys to a descendant cj_tree_entry_t*. */
+typedef struct {
+ enum { KEY, TREE } type;
+ union {
+ c_avl_tree_t *tree;
+ cj_key_t *key;
+ };
+} cj_tree_entry_t;
+
+/* cj_state_t is a stack providing the configuration relevant for the context
+ * that is currently being parsed. If entry->type == KEY, the parser should
+ * expect a metric (a numeric value). If entry->type == TREE, the parser should
+ * expect an array of map to descent into. If entry == NULL, no configuration
+ * exists for this part of the JSON structure. */
+typedef struct {
+ cj_tree_entry_t *entry;
+ _Bool in_array;
+ int index;
+ char name[DATA_MAX_NAME_LEN];
+} cj_state_t;
+
struct cj_s /* {{{ */
{
char *instance;
yajl_handle yajl;
c_avl_tree_t *tree;
- cj_key_t *key;
int depth;
- struct {
- union {
- c_avl_tree_t *tree;
- cj_key_t *key;
- };
- _Bool in_array;
- int index;
- char name[DATA_MAX_NAME_LEN];
- } state[YAJL_MAX_DEPTH];
+ cj_state_t state[YAJL_MAX_DEPTH];
};
typedef struct cj_s cj_t; /* }}} */
#endif
static int cj_read(user_data_t *ud);
-static void cj_submit(cj_t *db, cj_key_t *key, value_t *value);
+static void cj_submit_impl(cj_t *db, cj_key_t *key, value_t *value);
+
+/* cj_submit is a function pointer to cj_submit_impl, allowing the unit-test to
+ * overwrite which function is called. */
+static void (*cj_submit)(cj_t *, cj_key_t *, value_t *) = cj_submit_impl;
static size_t cj_curl_callback(void *buf, /* {{{ */
size_t size, size_t nmemb, void *user_data) {
len = size * nmemb;
if (len == 0)
- return (len);
+ return len;
db = user_data;
if (db == NULL)
- return (0);
+ return 0;
status = yajl_parse(db->yajl, (unsigned char *)buf, len);
if (status == yajl_status_ok)
- return (len);
+ return len;
#if !HAVE_YAJL_V2
else if (status == yajl_status_insufficient_data)
- return (len);
+ return len;
#endif
unsigned char *msg =
/* jsonText = */ (unsigned char *)buf, (unsigned int)len);
ERROR("curl_json plugin: yajl_parse failed: %s", msg);
yajl_free_error(db->yajl, msg);
- return (0); /* abort write callback */
+ return 0; /* abort write callback */
} /* }}} size_t cj_curl_callback */
static int cj_get_type(cj_key_t *key) {
- const data_set_t *ds;
-
- if ((key == NULL) || !CJ_IS_KEY(key))
+ if (key == NULL)
return -EINVAL;
- ds = plugin_get_ds(key->type);
+ const data_set_t *ds = plugin_get_ds(key->type);
if (ds == NULL) {
static char type[DATA_MAX_NAME_LEN] = "!!!invalid!!!";
sstrncpy(db->state[db->depth].name, key, sizeof(db->state[db->depth].name));
- c_avl_tree_t *tree = db->state[db->depth - 1].tree;
- if (tree == NULL) {
+ if (db->state[db->depth - 1].entry == NULL ||
+ db->state[db->depth - 1].entry->type != TREE) {
return 0;
}
- /* the parent has a key, so the tree pointer is invalid. */
- if (CJ_IS_KEY(db->state[db->depth - 1].key)) {
- return 0;
- }
+ c_avl_tree_t *tree = db->state[db->depth - 1].entry->tree;
+ cj_tree_entry_t *e = NULL;
- void *value = NULL;
- if (c_avl_get(tree, key, (void *)&value) == 0) {
- if (CJ_IS_KEY((cj_key_t *)value)) {
- db->state[db->depth].key = value;
- } else {
- db->state[db->depth].tree = value;
- }
- } else if (c_avl_get(tree, CJ_ANY, (void *)&value) == 0) {
- if (CJ_IS_KEY((cj_key_t *)value)) {
- db->state[db->depth].key = value;
- } else {
- db->state[db->depth].tree = value;
- }
+ if (c_avl_get(tree, key, (void *)&e) == 0) {
+ db->state[db->depth].entry = e;
+ } else if (c_avl_get(tree, CJ_ANY, (void *)&e) == 0) {
+ db->state[db->depth].entry = e;
} else {
- db->state[db->depth].key = NULL;
+ db->state[db->depth].entry = NULL;
}
return 0;
static int cj_cb_boolean(void *ctx, int boolVal) {
cj_advance_array(ctx);
- return (CJ_CB_CONTINUE);
+ return CJ_CB_CONTINUE;
}
static int cj_cb_null(void *ctx) {
cj_advance_array(ctx);
- return (CJ_CB_CONTINUE);
+ return CJ_CB_CONTINUE;
}
static int cj_cb_number(void *ctx, const char *number, yajl_len_t number_len) {
- char buffer[number_len + 1];
-
cj_t *db = (cj_t *)ctx;
- cj_key_t *key = db->state[db->depth].key;
/* Create a null-terminated version of the string. */
+ char buffer[number_len + 1];
memcpy(buffer, number, number_len);
buffer[sizeof(buffer) - 1] = 0;
-
-
- if (key == NULL) {
- /* no config for this element. */
- cj_advance_array(ctx);
- return CJ_CB_CONTINUE;
- } else if (!CJ_IS_KEY(key)) {
- /* the config expects a map or an array. */
- NOTICE(
- "curl_json plugin: Found \"%s\", but the configuration expects a map.",
- buffer);
+ if (db->state[db->depth].entry == NULL ||
+ db->state[db->depth].entry->type != KEY) {
+ if (db->state[db->depth].entry != NULL) {
+ NOTICE("curl_json plugin: Found \"%s\", but the configuration expects a "
+ "map.",
+ buffer);
+ }
cj_advance_array(ctx);
return CJ_CB_CONTINUE;
}
+ cj_key_t *key = db->state[db->depth].entry->key;
+
int type = cj_get_type(key);
value_t vt;
int status = parse_value(buffer, &vt, type);
if (status != 0) {
NOTICE("curl_json plugin: Unable to parse number: \"%s\"", buffer);
cj_advance_array(ctx);
- return (CJ_CB_CONTINUE);
+ return CJ_CB_CONTINUE;
}
cj_submit(db, key, &vt);
cj_advance_array(ctx);
- return (CJ_CB_CONTINUE);
+ return CJ_CB_CONTINUE;
} /* int cj_cb_number */
/* Queries the key-tree of the parent context for "in_name" and, if found,
static int cj_cb_string(void *ctx, const unsigned char *val, yajl_len_t len) {
/* Handle the string as if it was a number. */
- return (cj_cb_number(ctx, (const char *)val, len));
+ return cj_cb_number(ctx, (const char *)val, len);
} /* int cj_cb_string */
static int cj_cb_end(void *ctx) {
cj_t *db = (cj_t *)ctx;
- db->state[db->depth].tree = NULL;
+ memset(&db->state[db->depth], 0, sizeof(db->state[db->depth]));
db->depth--;
cj_advance_array(ctx);
- return (CJ_CB_CONTINUE);
+ return CJ_CB_CONTINUE;
}
static int cj_cb_start_map(void *ctx) {
if ((db->depth + 1) >= YAJL_MAX_DEPTH) {
ERROR("curl_json plugin: %s depth exceeds max, aborting.",
db->url ? db->url : db->sock);
- return (CJ_CB_ABORT);
+ return CJ_CB_ABORT;
}
db->depth++;
- return (CJ_CB_CONTINUE);
+ return CJ_CB_CONTINUE;
}
static int cj_cb_end_map(void *ctx) { return cj_cb_end(ctx); }
static void cj_tree_free(c_avl_tree_t *tree) /* {{{ */
{
char *name;
- void *value;
+ cj_tree_entry_t *e;
- while (c_avl_pick(tree, (void *)&name, (void *)&value) == 0) {
- cj_key_t *key = (cj_key_t *)value;
+ while (c_avl_pick(tree, (void *)&name, (void *)&e) == 0) {
+ sfree(name);
- if (CJ_IS_KEY(key))
- cj_key_free(key);
+ if (e->type == KEY)
+ cj_key_free(e->key);
else
- cj_tree_free((c_avl_tree_t *)value);
-
- sfree(name);
+ cj_tree_free(e->tree);
+ sfree(e);
}
c_avl_destroy(tree);
struct curl_slist *temp = NULL;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("curl_json plugin: `%s' needs exactly one string argument.", name);
- return (-1);
+ return -1;
}
temp = curl_slist_append(*dest, ci->values[0].value.string);
if (temp == NULL)
- return (-1);
+ return -1;
*dest = temp;
- return (0);
+ return 0;
} /* }}} int cj_config_append_string */
+/* cj_append_key adds key to the configuration stored in db.
+ *
+ * For example:
+ * "httpd/requests/count",
+ * "httpd/requests/current" ->
+ * { "httpd": { "requests": { "count": $key, "current": $key } } }
+ */
+static int cj_append_key(cj_t *db, cj_key_t *key) { /* {{{ */
+ if (db->tree == NULL)
+ db->tree = cj_avl_create();
+
+ c_avl_tree_t *tree = db->tree;
+
+ char const *start = key->path;
+ if (*start == '/')
+ ++start;
+
+ char const *end;
+ while ((end = strchr(start, '/')) != NULL) {
+ char name[PATH_MAX];
+
+ size_t len = end - start;
+ if (len == 0)
+ break;
+
+ len = COUCH_MIN(len, sizeof(name) - 1);
+ sstrncpy(name, start, len + 1);
+
+ cj_tree_entry_t *e;
+ if (c_avl_get(tree, name, (void *)&e) != 0) {
+ e = calloc(1, sizeof(*e));
+ if (e == NULL)
+ return ENOMEM;
+ e->type = TREE;
+ e->tree = cj_avl_create();
+
+ c_avl_insert(tree, strdup(name), e);
+ }
+
+ if (e->type != TREE)
+ return EINVAL;
+
+ tree = e->tree;
+ start = end + 1;
+ }
+
+ if (strlen(start) == 0) {
+ ERROR("curl_json plugin: invalid key: %s", key->path);
+ return -1;
+ }
+
+ cj_tree_entry_t *e = calloc(1, sizeof(*e));
+ if (e == NULL)
+ return ENOMEM;
+ e->type = KEY;
+ e->key = key;
+
+ c_avl_insert(tree, strdup(start), e);
+ return 0;
+} /* }}} int cj_append_key */
+
static int cj_config_add_key(cj_t *db, /* {{{ */
oconfig_item_t *ci) {
cj_key_t *key;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("curl_json plugin: The `Key' block "
"needs exactly one string argument.");
- return (-1);
+ return -1;
}
key = calloc(1, sizeof(*key));
if (key == NULL) {
ERROR("curl_json plugin: calloc failed.");
- return (-1);
+ return -1;
}
- key->magic = CJ_KEY_MAGIC;
if (strcasecmp("Key", ci->key) == 0) {
status = cf_util_get_string(ci, &key->path);
if (status != 0) {
sfree(key);
- return (status);
+ return status;
}
} else {
ERROR("curl_json plugin: cj_config: "
"Invalid key: %s",
ci->key);
cj_key_free(key);
- return (-1);
+ return -1;
}
status = 0;
if (status != 0) {
cj_key_free(key);
- return (-1);
+ return -1;
}
if (key->type == NULL) {
WARNING("curl_json plugin: `Type' missing in `Key' block.");
cj_key_free(key);
- return (-1);
- }
-
- /* store path in a tree that will match the json map structure, example:
- * "httpd/requests/count",
- * "httpd/requests/current" ->
- * { "httpd": { "requests": { "count": $key, "current": $key } } }
- */
- char *ptr;
- char *name;
- c_avl_tree_t *tree;
-
- if (db->tree == NULL)
- db->tree = cj_avl_create();
-
- tree = db->tree;
- ptr = key->path;
- if (*ptr == '/')
- ++ptr;
-
- name = ptr;
- while ((ptr = strchr(name, '/')) != NULL) {
- char ent[PATH_MAX];
- c_avl_tree_t *value;
- size_t len;
-
- len = ptr - name;
- if (len == 0)
- break;
-
- len = COUCH_MIN(len, sizeof(ent) - 1);
- sstrncpy(ent, name, len + 1);
-
- if (c_avl_get(tree, ent, (void *)&value) != 0) {
- value = cj_avl_create();
- c_avl_insert(tree, strdup(ent), value);
- }
-
- tree = value;
- name = ptr + 1;
+ return -1;
}
- if (strlen(name) == 0) {
- ERROR("curl_json plugin: invalid key: %s", key->path);
+ status = cj_append_key(db, key);
+ if (status != 0) {
cj_key_free(key);
- return (-1);
+ return -1;
}
- c_avl_insert(tree, strdup(name), key);
- return (status);
+ return 0;
} /* }}} int cj_config_add_key */
static int cj_init_curl(cj_t *db) /* {{{ */
db->curl = curl_easy_init();
if (db->curl == NULL) {
ERROR("curl_json plugin: curl_easy_init failed.");
- return (-1);
+ return -1;
}
curl_easy_setopt(db->curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(db->curl, CURLOPT_WRITEDATA, db);
curl_easy_setopt(db->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt(db->curl, CURLOPT_ERRORBUFFER, db->curl_errbuf);
- curl_easy_setopt(db->curl, CURLOPT_URL, db->url);
curl_easy_setopt(db->curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(db->curl, CURLOPT_MAXREDIRS, 50L);
db->credentials = malloc(credentials_size);
if (db->credentials == NULL) {
ERROR("curl_json plugin: malloc failed.");
- return (-1);
+ return -1;
}
ssnprintf(db->credentials, credentials_size, "%s:%s", db->user,
(long)CDTIME_T_TO_MS(plugin_get_interval()));
#endif
- return (0);
+ return 0;
} /* }}} int cj_init_curl */
static int cj_config_add_url(oconfig_item_t *ci) /* {{{ */
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("curl_json plugin: The `URL' block "
"needs exactly one string argument.");
- return (-1);
+ return -1;
}
db = calloc(1, sizeof(*db));
if (db == NULL) {
ERROR("curl_json plugin: calloc failed.");
- return (-1);
+ return -1;
}
db->timeout = -1;
"Invalid key: %s",
ci->key);
cj_free(db);
- return (-1);
+ return -1;
}
if (status != 0) {
sfree(db);
- return (status);
+ return status;
}
/* Fill the `cj_t' structure.. */
sfree(cb_name);
} else {
cj_free(db);
- return (-1);
+ return -1;
}
- return (0);
+ return 0;
}
/* }}} int cj_config_add_database */
if ((success == 0) && (errors > 0)) {
ERROR("curl_json plugin: All statements failed.");
- return (-1);
+ return -1;
}
- return (0);
+ return 0;
} /* }}} int cj_config */
/* }}} End of configuration handling functions */
return db->host;
} /* }}} cj_host */
-static void cj_submit(cj_t *db, cj_key_t *key, value_t *value) /* {{{ */
+static void cj_submit_impl(cj_t *db, cj_key_t *key, value_t *value) /* {{{ */
{
value_list_t vl = VALUE_LIST_INIT;
vl.interval = db->interval;
plugin_dispatch_values(&vl);
-} /* }}} int cj_submit */
+} /* }}} int cj_submit_impl */
static int cj_sock_perform(cj_t *db) /* {{{ */
{
char errbuf[1024];
- struct sockaddr_un sa_unix = {0};
- sa_unix.sun_family = AF_UNIX;
+ struct sockaddr_un sa_unix = {
+ .sun_family = AF_UNIX,
+ };
sstrncpy(sa_unix.sun_path, db->sock, sizeof(sa_unix.sun_path));
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0)
- return (-1);
+ return -1;
if (connect(fd, (struct sockaddr *)&sa_unix, sizeof(sa_unix)) < 0) {
ERROR("curl_json plugin: connect(%s) failed: %s",
(db->sock != NULL) ? db->sock : "<null>",
sstrerror(errno, errbuf, sizeof(errbuf)));
close(fd);
- return (-1);
+ return -1;
}
ssize_t red;
(db->sock != NULL) ? db->sock : "<null>",
sstrerror(errno, errbuf, sizeof(errbuf)));
close(fd);
- return (-1);
+ return -1;
}
if (!cj_curl_callback(buffer, red, 1, db))
break;
} while (red > 0);
close(fd);
- return (0);
+ return 0;
} /* }}} int cj_sock_perform */
static int cj_curl_perform(cj_t *db) /* {{{ */
int status;
long rc;
char *url;
- url = db->url;
+
+ curl_easy_setopt(db->curl, CURLOPT_URL, db->url);
status = curl_easy_perform(db->curl);
if (status != CURLE_OK) {
ERROR("curl_json plugin: curl_easy_perform failed with status %i: %s (%s)",
- status, db->curl_errbuf, url);
+ status, db->curl_errbuf, db->url);
- return (-1);
+ return -1;
}
if (db->stats != NULL)
curl_stats_dispatch(db->stats, db->curl, cj_host(db), "curl_json",
ERROR("curl_json plugin: curl_easy_perform failed with "
"response code %ld (%s)",
rc, url);
- return (-1);
+ return -1;
}
- return (0);
+ return 0;
} /* }}} int cj_curl_perform */
static int cj_perform(cj_t *db) /* {{{ */
if (db->yajl == NULL) {
ERROR("curl_json plugin: yajl_alloc failed.");
db->yajl = yprev;
- return (-1);
+ return -1;
}
if (db->url)
if (status < 0) {
yajl_free(db->yajl);
db->yajl = yprev;
- return (-1);
+ return -1;
}
#if HAVE_YAJL_V2
yajl_free_error(db->yajl, errmsg);
yajl_free(db->yajl);
db->yajl = yprev;
- return (-1);
+ return -1;
}
yajl_free(db->yajl);
db->yajl = yprev;
- return (0);
+ return 0;
} /* }}} int cj_perform */
static int cj_read(user_data_t *ud) /* {{{ */
if ((ud == NULL) || (ud->data == NULL)) {
ERROR("curl_json plugin: cj_read: Invalid user data.");
- return (-1);
+ return -1;
}
db = (cj_t *)ud->data;
db->depth = 0;
memset(&db->state, 0, sizeof(db->state));
- db->state[db->depth].tree = db->tree;
- db->key = NULL;
- return cj_perform(db);
+ /* This is not a compound literal because EPEL6's GCC is not cool enough to
+ * handle anonymous unions within compound literals. */
+ cj_tree_entry_t root = {0};
+ root.type = TREE;
+ root.tree = db->tree;
+ db->state[0].entry = &root;
+
+ int status = cj_perform(db);
+
+ db->state[0].entry = NULL;
+
+ return status;
} /* }}} int cj_read */
static int cj_init(void) /* {{{ */
/* Call this while collectd is still single-threaded to avoid
* initialization issues in libgcrypt. */
curl_global_init(CURL_GLOBAL_SSL);
- return (0);
+ return 0;
} /* }}} int cj_init */
void module_register(void) {
plugin_register_complex_config("curl_json", cj_config);
plugin_register_init("curl_json", cj_init);
} /* void module_register */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
if (db == NULL) {
ERROR("curl_xml plugin: cx_curl_callback: "
"user_data pointer is NULL.");
- return (0);
+ return 0;
}
if (len == 0)
- return (len);
+ return len;
if ((db->buffer_fill + len) >= db->buffer_size) {
char *temp;
temp = realloc(db->buffer, db->buffer_fill + len + 1);
if (temp == NULL) {
ERROR("curl_xml plugin: realloc failed.");
- return (0);
+ return 0;
}
db->buffer = temp;
db->buffer_size = db->buffer_fill + len + 1;
db->buffer_fill += len;
db->buffer[db->buffer_fill] = 0;
- return (len);
+ return len;
} /* }}} size_t cx_curl_callback */
static void cx_xpath_free(cx_xpath_t *xpath) /* {{{ */
struct curl_slist *temp = NULL;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("curl_xml plugin: `%s' needs exactly one string argument.", name);
- return (-1);
+ return -1;
}
temp = curl_slist_append(*dest, ci->values[0].value.string);
if (temp == NULL)
- return (-1);
+ return -1;
*dest = temp;
- return (0);
+ return 0;
} /* }}} int cx_config_append_string */
static int cx_check_type(const data_set_t *ds, cx_xpath_t *xpath) /* {{{ */
{
if (!ds) {
WARNING("curl_xml plugin: DataSet `%s' not defined.", xpath->type);
- return (-1);
+ return -1;
}
if (ds->ds_num != xpath->values_len) {
WARNING("curl_xml plugin: DataSet `%s' requires %zu values, but config "
"talks about %zu",
xpath->type, ds->ds_num, xpath->values_len);
- return (-1);
+ return -1;
}
- return (0);
+ return 0;
} /* }}} cx_check_type */
static xmlXPathObjectPtr
{
if (node->type == XML_TEXT_NODE || node->type == XML_ATTRIBUTE_NODE ||
node->type == XML_ELEMENT_NODE)
- return (0);
+ return 0;
WARNING("curl_xml plugin: "
"Node \"%s\" doesn't seem to be a text node. Skipping...",
values_node_obj =
cx_evaluate_xpath(xpath_ctx, BAD_CAST xpath->values[index].path);
if (values_node_obj == NULL)
- return (-1); /* Error already logged. */
+ return -1; /* Error already logged. */
values_node = values_node_obj->nodesetval;
tmp_size = (values_node) ? values_node->nodeNr : 0;
"Skipping...",
xpath->values[index].path);
xmlXPathFreeObject(values_node_obj);
- return (-1);
+ return -1;
}
if (tmp_size > 1) {
"only one node. Skipping...",
xpath->values[index].path);
xmlXPathFreeObject(values_node_obj);
- return (-1);
+ return -1;
}
/* ignoring the element if other than textnode/attribute*/
"only text/attribute node which is not the case. Skipping...",
xpath->values[index].path);
xmlXPathFreeObject(values_node_obj);
- return (-1);
+ return -1;
}
node_value = (char *)xmlNodeGetContent(values_node->nodeTab[0]);
/* We have reached here which means that
* we have got something to work */
- return (0);
+ return 0;
} /* }}} int cx_handle_single_value_xpath */
static int cx_handle_all_value_xpaths(xmlXPathContextPtr xpath_ctx, /* {{{ */
for (size_t i = 0; i < xpath->values_len; i++) {
status = cx_handle_single_value_xpath(xpath_ctx, xpath, ds, vl, i);
if (status != 0)
- return (-1); /* An error has been printed. */
+ return -1; /* An error has been printed. */
} /* for (i = 0; i < xpath->values_len; i++) */
plugin_dispatch_values(vl);
vl->values = NULL;
- return (0);
+ return 0;
} /* }}} int cx_handle_all_value_xpaths */
static int cx_handle_instance_xpath(xmlXPathContextPtr xpath_ctx, /* {{{ */
"Base-XPath %s is a table (more than one result was returned), "
"but no instance-XPath has been defined.",
xpath->path);
- return (-1);
+ return -1;
}
/* instance has to be an xpath expression */
instance_node_obj = cx_evaluate_xpath(xpath_ctx, BAD_CAST xpath->instance);
if (instance_node_obj == NULL)
- return (-1); /* error is logged already */
+ return -1; /* error is logged already */
instance_node = instance_node_obj->nodesetval;
tmp_size = (instance_node) ? instance_node->nodeNr : 0;
"any of the nodes. Skipping the node.",
xpath->instance);
xmlXPathFreeObject(instance_node_obj);
- return (-1);
+ return -1;
}
if (tmp_size > 1) {
"to return only one text node. Skipping the node.",
xpath->instance);
xmlXPathFreeObject(instance_node_obj);
- return (-1);
+ return -1;
}
/* ignoring the element if other than textnode/attribute */
"which is not the case. Skipping the node.",
xpath->instance);
xmlXPathFreeObject(instance_node_obj);
- return (-1);
+ return -1;
}
} /* if (xpath->instance != NULL) */
* somewhere inside this structure. */
xmlXPathFreeObject(instance_node_obj);
- return (0);
+ return 0;
} /* }}} int cx_handle_instance_xpath */
static int cx_handle_base_xpath(char const *plugin_instance, /* {{{ */
/* free up the allocated memory */
xmlXPathFreeObject(base_node_obj);
- return (0);
+ return 0;
} /* }}} cx_handle_base_xpath */
static int cx_handle_parsed_xml(xmlDocPtr doc, /* {{{ */
doc = xmlParseDoc(xml);
if (doc == NULL) {
ERROR("curl_xml plugin: Failed to parse the xml document - %s", xml);
- return (-1);
+ return -1;
}
xpath_ctx = xmlXPathNewContext(doc);
if (xpath_ctx == NULL) {
ERROR("curl_xml plugin: Failed to create the xml context");
xmlFreeDoc(doc);
- return (-1);
+ return -1;
}
for (size_t i = 0; i < db->namespaces_num; i++) {
ns->prefix, ns->url);
xmlXPathFreeContext(xpath_ctx);
xmlFreeDoc(doc);
- return (status);
+ return status;
}
}
long rc;
char *ptr;
char *url;
- url = db->url;
db->buffer_fill = 0;
+
+ curl_easy_setopt(db->curl, CURLOPT_URL, db->url);
+
status = curl_easy_perform(curl);
if (status != CURLE_OK) {
ERROR("curl_xml plugin: curl_easy_perform failed with status %i: %s (%s)",
- status, db->curl_errbuf, url);
+ status, db->curl_errbuf, db->url);
- return (-1);
+ return -1;
}
if (db->stats != NULL)
curl_stats_dispatch(db->stats, db->curl, cx_host(db), "curl_xml",
ERROR(
"curl_xml plugin: curl_easy_perform failed with response code %ld (%s)",
rc, url);
- return (-1);
+ return -1;
}
ptr = db->buffer;
if ((ud == NULL) || (ud->data == NULL)) {
ERROR("curl_xml plugin: cx_read: Invalid user data.");
- return (-1);
+ return -1;
}
db = (cx_t *)ud->data;
oconfig_item_t *ci) {
if (ci->values_num < 1) {
WARNING("curl_xml plugin: `ValuesFrom' needs at least one argument.");
- return (-1);
+ return -1;
}
for (int i = 0; i < ci->values_num; i++)
if (ci->values[i].type != OCONFIG_TYPE_STRING) {
WARNING("curl_xml plugin: `ValuesFrom' needs only string argument.");
- return (-1);
+ return -1;
}
sfree(xpath->values);
xpath->values_len = 0;
xpath->values = malloc(sizeof(cx_values_t) * ci->values_num);
if (xpath->values == NULL)
- return (-1);
+ return -1;
xpath->values_len = (size_t)ci->values_num;
/* populate cx_values_t structure */
sizeof(xpath->values[i].path));
}
- return (0);
+ return 0;
} /* }}} cx_config_add_values */
static int cx_config_add_xpath(cx_t *db, oconfig_item_t *ci) /* {{{ */
xpath = calloc(1, sizeof(*xpath));
if (xpath == NULL) {
ERROR("curl_xml plugin: calloc failed.");
- return (-1);
+ return -1;
}
status = cf_util_get_string(ci, &xpath->path);
if (status != 0) {
cx_xpath_free(xpath);
- return (status);
+ return status;
}
/* error out if xpath->path is an empty string */
ERROR("curl_xml plugin: invalid xpath. "
"xpath value can't be an empty string");
cx_xpath_free(xpath);
- return (-1);
+ return -1;
}
status = 0;
if (db->list == NULL) {
ERROR("curl_xml plugin: list creation failed.");
cx_xpath_free(xpath);
- return (-1);
+ return -1;
}
}
if (name == NULL) {
ERROR("curl_xml plugin: strdup failed.");
cx_xpath_free(xpath);
- return (-1);
+ return -1;
}
le = llentry_create(name, xpath);
ERROR("curl_xml plugin: llentry_create failed.");
cx_xpath_free(xpath);
sfree(name);
- return (-1);
+ return -1;
}
llist_append(db->list, le);
- return (0);
+ return 0;
} /* }}} int cx_config_add_xpath */
static int cx_config_add_namespace(cx_t *db, /* {{{ */
(ci->values[1].type != OCONFIG_TYPE_STRING)) {
WARNING("curl_xml plugin: The `Namespace' option "
"needs exactly two string arguments.");
- return (EINVAL);
+ return EINVAL;
}
ns = realloc(db->namespaces,
sizeof(*db->namespaces) * (db->namespaces_num + 1));
if (ns == NULL) {
ERROR("curl_xml plugin: realloc failed.");
- return (ENOMEM);
+ return ENOMEM;
}
db->namespaces = ns;
ns = db->namespaces + db->namespaces_num;
sfree(ns->prefix);
sfree(ns->url);
ERROR("curl_xml plugin: strdup failed.");
- return (ENOMEM);
+ return ENOMEM;
}
db->namespaces_num++;
- return (0);
+ return 0;
} /* }}} int cx_config_add_namespace */
/* Initialize db->curl */
db->curl = curl_easy_init();
if (db->curl == NULL) {
ERROR("curl_xml plugin: curl_easy_init failed.");
- return (-1);
+ return -1;
}
curl_easy_setopt(db->curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(db->curl, CURLOPT_WRITEDATA, db);
curl_easy_setopt(db->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt(db->curl, CURLOPT_ERRORBUFFER, db->curl_errbuf);
- curl_easy_setopt(db->curl, CURLOPT_URL, db->url);
curl_easy_setopt(db->curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(db->curl, CURLOPT_MAXREDIRS, 50L);
db->credentials = malloc(credentials_size);
if (db->credentials == NULL) {
ERROR("curl_xml plugin: malloc failed.");
- return (-1);
+ return -1;
}
ssnprintf(db->credentials, credentials_size, "%s:%s", db->user,
(long)CDTIME_T_TO_MS(plugin_get_interval()));
#endif
- return (0);
+ return 0;
} /* }}} int cx_init_curl */
static int cx_config_add_url(oconfig_item_t *ci) /* {{{ */
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("curl_xml plugin: The `URL' block "
"needs exactly one string argument.");
- return (-1);
+ return -1;
}
db = calloc(1, sizeof(*db));
if (db == NULL) {
ERROR("curl_xml plugin: calloc failed.");
- return (-1);
+ return -1;
}
db->timeout = -1;
status = cf_util_get_string(ci, &db->url);
if (status != 0) {
sfree(db);
- return (status);
+ return status;
}
} else {
ERROR("curl_xml plugin: cx_config: "
"Invalid key: %s",
ci->key);
cx_free(db);
- return (-1);
+ return -1;
}
/* Fill the `cx_t' structure.. */
sfree(cb_name);
} else {
cx_free(db);
- return (-1);
+ return -1;
}
- return (0);
+ return 0;
} /* }}} int cx_config_add_url */
/* }}} End of configuration handling functions */
if ((success == 0) && (errors > 0)) {
ERROR("curl_xml plugin: All statements failed.");
- return (-1);
+ return -1;
}
- return (0);
+ return 0;
} /* }}} int cx_config */
static int cx_init(void) /* {{{ */
/* Call this while collectd is still single-threaded to avoid
* initialization issues in libgcrypt. */
curl_global_init(CURL_GLOBAL_SSL);
- return (0);
+ return 0;
} /* }}} int cx_init */
void module_register(void) {
plugin_register_complex_config("curl_xml", cx_config);
plugin_register_init("curl_xml", cx_init);
} /* void module_register */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */
}
if (len == 0)
- return (len);
+ return len;
memcpy(&nginx_buffer[nginx_buffer_len], buf, len);
nginx_buffer_len += len;
nginx_buffer[nginx_buffer_len] = 0;
- return (len);
+ return len;
}
static int config_set(char **var, const char *value) {
}
if ((*var = strdup(value)) == NULL)
- return (1);
+ return 1;
else
- return (0);
+ return 0;
}
static int config(const char *key, const char *value) {
if (strcasecmp(key, "url") == 0)
- return (config_set(&url, value));
+ return config_set(&url, value);
else if (strcasecmp(key, "user") == 0)
- return (config_set(&user, value));
+ return config_set(&user, value);
else if (strcasecmp(key, "password") == 0)
- return (config_set(&pass, value));
+ return config_set(&pass, value);
else if (strcasecmp(key, "verifypeer") == 0)
- return (config_set(&verify_peer, value));
+ return config_set(&verify_peer, value);
else if (strcasecmp(key, "verifyhost") == 0)
- return (config_set(&verify_host, value));
+ return config_set(&verify_host, value);
else if (strcasecmp(key, "cacert") == 0)
- return (config_set(&cacert, value));
+ return config_set(&cacert, value);
else if (strcasecmp(key, "timeout") == 0)
- return (config_set(&timeout, value));
+ return config_set(&timeout, value);
else
- return (-1);
+ return -1;
} /* int config */
static int init(void) {
if ((curl = curl_easy_init()) == NULL) {
ERROR("nginx plugin: curl_easy_init failed.");
- return (-1);
+ return -1;
}
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
pass == NULL ? "" : pass);
if ((status < 0) || ((size_t)status >= sizeof(credentials))) {
ERROR("nginx plugin: Credentials would have been truncated.");
- return (-1);
+ return -1;
}
curl_easy_setopt(curl, CURLOPT_USERPWD, credentials);
#endif
}
- if (url != NULL) {
- curl_easy_setopt(curl, CURLOPT_URL, url);
- }
-
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
}
#endif
- return (0);
+ return 0;
} /* void init */
static void submit(const char *type, const char *inst, long long value) {
int fields_num;
if (curl == NULL)
- return (-1);
+ return -1;
if (url == NULL)
- return (-1);
+ return -1;
nginx_buffer_len = 0;
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+
if (curl_easy_perform(curl) != CURLE_OK) {
WARNING("nginx plugin: curl_easy_perform failed: %s", nginx_curl_error);
- return (-1);
+ return -1;
}
ptr = nginx_buffer;
nginx_buffer_len = 0;
- return (0);
+ return 0;
} /* int nginx_read */
void module_register(void) {
plugin_register_init("nginx", init);
plugin_register_read("nginx", nginx_read);
} /* void module_register */
-
-/*
- * vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
- */
cdtime_t send_buffer_init_time;
pthread_mutex_t send_lock;
+
+ int data_ttl;
};
typedef struct wh_callback_s wh_callback_t;
+static char **http_attrs;
+static size_t http_attrs_num;
+
static void wh_log_http_error(wh_callback_t *cb) {
if (!cb->log_http_error)
return;
{
int status = 0;
+ curl_easy_setopt(cb->curl, CURLOPT_URL, cb->location);
curl_easy_setopt(cb->curl, CURLOPT_POSTFIELDS, data);
status = curl_easy_perform(cb->curl);
"status %i: %s",
status, cb->curl_errbuf);
}
- return (status);
+ return status;
} /* }}} wh_post_nolock */
static int wh_callback_init(wh_callback_t *cb) /* {{{ */
{
if (cb->curl != NULL)
- return (0);
+ return 0;
cb->curl = curl_easy_init();
if (cb->curl == NULL) {
ERROR("curl plugin: curl_easy_init failed.");
- return (-1);
+ return -1;
}
if (cb->low_speed_limit > 0 && cb->low_speed_time > 0) {
curl_easy_setopt(cb->curl, CURLOPT_HTTPHEADER, cb->headers);
curl_easy_setopt(cb->curl, CURLOPT_ERRORBUFFER, cb->curl_errbuf);
- curl_easy_setopt(cb->curl, CURLOPT_URL, cb->location);
curl_easy_setopt(cb->curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(cb->curl, CURLOPT_MAXREDIRS, 50L);
cb->credentials = malloc(credentials_size);
if (cb->credentials == NULL) {
ERROR("curl plugin: malloc failed.");
- return (-1);
+ return -1;
}
ssnprintf(cb->credentials, credentials_size, "%s:%s", cb->user,
wh_reset_buffer(cb);
- return (0);
+ return 0;
} /* }}} int wh_callback_init */
static int wh_flush_nolock(cdtime_t timeout, wh_callback_t *cb) /* {{{ */
now = cdtime();
if ((cb->send_buffer_init_time + timeout) > now)
- return (0);
+ return 0;
}
if (cb->format == WH_FORMAT_COMMAND) {
if (cb->send_buffer_fill == 0) {
cb->send_buffer_init_time = cdtime();
- return (0);
+ return 0;
}
status = wh_post_nolock(cb, cb->send_buffer);
} else if (cb->format == WH_FORMAT_JSON || cb->format == WH_FORMAT_KAIROSDB) {
if (cb->send_buffer_fill <= 2) {
cb->send_buffer_init_time = cdtime();
- return (0);
+ return 0;
}
status = format_json_finalize(cb->send_buffer, &cb->send_buffer_fill,
ERROR("write_http: wh_flush_nolock: "
"format_json_finalize failed.");
wh_reset_buffer(cb);
- return (status);
+ return status;
}
status = wh_post_nolock(cb, cb->send_buffer);
ERROR("write_http: wh_flush_nolock: "
"Unknown format: %i",
cb->format);
- return (-1);
+ return -1;
}
- return (status);
+ return status;
} /* }}} wh_flush_nolock */
static int wh_flush(cdtime_t timeout, /* {{{ */
int status;
if (user_data == NULL)
- return (-EINVAL);
+ return -EINVAL;
cb = user_data->data;
if (wh_callback_init(cb) != 0) {
ERROR("write_http plugin: wh_callback_init failed.");
pthread_mutex_unlock(&cb->send_lock);
- return (-1);
+ return -1;
}
status = wh_flush_nolock(timeout, cb);
pthread_mutex_unlock(&cb->send_lock);
- return (status);
+ return status;
} /* }}} int wh_flush */
static void wh_callback_free(void *data) /* {{{ */
status = FORMAT_VL(key, sizeof(key), vl);
if (status != 0) {
ERROR("write_http plugin: error with format_name");
- return (status);
+ return status;
}
escape_string(key, sizeof(key));
if (status != 0) {
ERROR("write_http plugin: error with "
"wh_value_list_to_string");
- return (status);
+ return status;
}
command_len = (size_t)ssnprintf(command, sizeof(command),
ERROR("write_http plugin: Command buffer too small: "
"Need %zu bytes.",
command_len + 1);
- return (-1);
+ return -1;
}
pthread_mutex_lock(&cb->send_lock);
if (wh_callback_init(cb) != 0) {
ERROR("write_http plugin: wh_callback_init failed.");
pthread_mutex_unlock(&cb->send_lock);
- return (-1);
+ return -1;
}
if (command_len >= cb->send_buffer_free) {
status = wh_flush_nolock(/* timeout = */ 0, cb);
if (status != 0) {
pthread_mutex_unlock(&cb->send_lock);
- return (status);
+ return status;
}
}
assert(command_len < cb->send_buffer_free);
/* Check if we have enough space for this command. */
pthread_mutex_unlock(&cb->send_lock);
- return (0);
+ return 0;
} /* }}} int wh_write_command */
static int wh_write_json(const data_set_t *ds, const value_list_t *vl, /* {{{ */
if (wh_callback_init(cb) != 0) {
ERROR("write_http plugin: wh_callback_init failed.");
pthread_mutex_unlock(&cb->send_lock);
- return (-1);
+ return -1;
}
status =
if (status != 0) {
wh_reset_buffer(cb);
pthread_mutex_unlock(&cb->send_lock);
- return (status);
+ return status;
}
status =
}
if (status != 0) {
pthread_mutex_unlock(&cb->send_lock);
- return (status);
+ return status;
}
DEBUG("write_http plugin: <%s> buffer %zu/%zu (%g%%)", cb->location,
/* Check if we have enough space for this command. */
pthread_mutex_unlock(&cb->send_lock);
- return (0);
+ return 0;
} /* }}} int wh_write_json */
static int wh_write_kairosdb(const data_set_t *ds,
if (status != 0) {
ERROR("write_http plugin: wh_callback_init failed.");
pthread_mutex_unlock(&cb->send_lock);
- return (-1);
+ return -1;
}
}
- status = format_kairosdb_value_list(cb->send_buffer, &cb->send_buffer_fill,
- &cb->send_buffer_free, ds, vl,
- cb->store_rates);
+ status = format_kairosdb_value_list(
+ cb->send_buffer, &cb->send_buffer_fill, &cb->send_buffer_free, ds, vl,
+ cb->store_rates, (char const *const *)http_attrs, http_attrs_num,
+ cb->data_ttl);
if (status == -ENOMEM) {
status = wh_flush_nolock(/* timeout = */ 0, cb);
if (status != 0) {
wh_reset_buffer(cb);
pthread_mutex_unlock(&cb->send_lock);
- return (status);
+ return status;
}
- status = format_kairosdb_value_list(cb->send_buffer, &cb->send_buffer_fill,
- &cb->send_buffer_free, ds, vl,
- cb->store_rates);
+ status = format_kairosdb_value_list(
+ cb->send_buffer, &cb->send_buffer_fill, &cb->send_buffer_free, ds, vl,
+ cb->store_rates, (char const *const *)http_attrs, http_attrs_num,
+ cb->data_ttl);
}
if (status != 0) {
pthread_mutex_unlock(&cb->send_lock);
- return (status);
+ return status;
}
DEBUG("write_http plugin: <%s> buffer %zu/%zu (%g%%)", cb->location,
/* Check if we have enough space for this command. */
pthread_mutex_unlock(&cb->send_lock);
- return (0);
+ return 0;
} /* }}} int wh_write_kairosdb */
static int wh_write(const data_set_t *ds, const value_list_t *vl, /* {{{ */
int status;
if (user_data == NULL)
- return (-EINVAL);
+ return -EINVAL;
cb = user_data->data;
assert(cb->send_metrics);
status = wh_write_command(ds, vl, cb);
break;
}
- return (status);
+ return status;
} /* }}} int wh_write */
static int wh_notify(notification_t const *n, user_data_t *ud) /* {{{ */
int status;
if ((ud == NULL) || (ud->data == NULL))
- return (EINVAL);
+ return EINVAL;
cb = ud->data;
assert(cb->send_notifications);
if (wh_callback_init(cb) != 0) {
ERROR("write_http plugin: wh_callback_init failed.");
pthread_mutex_unlock(&cb->send_lock);
- return (-1);
+ return -1;
}
status = wh_post_nolock(cb, alert);
pthread_mutex_unlock(&cb->send_lock);
- return (status);
+ return status;
} /* }}} int wh_notify */
static int config_set_format(wh_callback_t *cb, /* {{{ */
WARNING("write_http plugin: The `%s' config option "
"needs exactly one string argument.",
ci->key);
- return (-1);
+ return -1;
}
string = ci->values[0].value.string;
cb->format = WH_FORMAT_KAIROSDB;
else {
ERROR("write_http plugin: Invalid format string: %s", string);
- return (-1);
+ return -1;
}
- return (0);
+ return 0;
} /* }}} int config_set_format */
static int wh_config_append_string(const char *name,
struct curl_slist *temp = NULL;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("write_http plugin: `%s' needs exactly one string argument.", name);
- return (-1);
+ return -1;
}
temp = curl_slist_append(*dest, ci->values[0].value.string);
if (temp == NULL)
- return (-1);
+ return -1;
*dest = temp;
- return (0);
+ return 0;
} /* }}} int wh_config_append_string */
static int wh_config_node(oconfig_item_t *ci) /* {{{ */
cb = calloc(1, sizeof(*cb));
if (cb == NULL) {
ERROR("write_http plugin: calloc failed.");
- return (-1);
+ return -1;
}
cb->verify_peer = 1;
cb->verify_host = 1;
cb->headers = NULL;
cb->send_metrics = 1;
cb->send_notifications = 0;
+ cb->data_ttl = 0;
pthread_mutex_init(&cb->send_lock, /* attr = */ NULL);
status = cf_util_get_boolean(child, &cb->log_http_error);
else if (strcasecmp("Header", child->key) == 0)
status = wh_config_append_string("Header", &cb->headers, child);
- else {
+ else if (strcasecmp("Attribute", child->key) == 0) {
+ char *key = NULL;
+ char *val = NULL;
+
+ if (child->values_num != 2) {
+ WARNING("write_http plugin: Attribute need both a key and a value.");
+ break;
+ }
+ if (child->values[0].type != OCONFIG_TYPE_STRING ||
+ child->values[1].type != OCONFIG_TYPE_STRING) {
+ WARNING("write_http plugin: Attribute needs string arguments.");
+ break;
+ }
+ if ((key = strdup(child->values[0].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute key.");
+ break;
+ }
+ if ((val = strdup(child->values[1].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute value.");
+ sfree(key);
+ break;
+ }
+ strarray_add(&http_attrs, &http_attrs_num, key);
+ strarray_add(&http_attrs, &http_attrs_num, val);
+ DEBUG("write_http plugin: got attribute: %s => %s", key, val);
+ sfree(key);
+ sfree(val);
+ } else if (strcasecmp("TTL", child->key) == 0) {
+ status = cf_util_get_int(child, &cb->data_ttl);
+ } else {
ERROR("write_http plugin: Invalid configuration "
"option: %s.",
child->key);
if (status != 0) {
wh_callback_free(cb);
- return (status);
+ return status;
}
if (cb->location == NULL) {
ERROR("write_http plugin: no URL defined for instance '%s'", cb->name);
wh_callback_free(cb);
- return (-1);
+ return -1;
}
if (!cb->send_metrics && !cb->send_notifications) {
"are enabled for \"%s\".",
cb->name);
wh_callback_free(cb);
- return (-1);
+ return -1;
}
if (cb->low_speed_limit > 0)
if (cb->send_buffer == NULL) {
ERROR("write_http plugin: malloc(%zu) failed.", cb->send_buffer_size);
wh_callback_free(cb);
- return (-1);
+ return -1;
}
/* Nulls the buffer and sets ..._free and ..._fill. */
wh_reset_buffer(cb);
user_data.free_func = NULL;
}
- return (0);
+ return 0;
} /* }}} int wh_config_node */
static int wh_config(oconfig_item_t *ci) /* {{{ */
}
}
- return (0);
+ 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);
+ 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 : */