#include "utils_avltree.h"
#include "utils_complain.h"
-#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
char *cacert;
struct curl_slist *headers;
char *post_body;
+ cdtime_t interval;
+ int timeout;
CURL *curl;
char curl_errbuf[CURL_ERROR_SIZE];
return (len);
#endif
- if (status != yajl_status_ok)
- {
- unsigned char *msg =
- yajl_get_error(db->yajl, /* verbose = */ 1,
- /* 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 (len);
+ unsigned char *msg = yajl_get_error(db->yajl, /* verbose = */ 1,
+ /* 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 */
} /* }}} size_t cj_curl_callback */
static int cj_get_type (cj_key_t *key)
buffer[sizeof (buffer) - 1] = 0;
if ((key == NULL) || !CJ_IS_KEY (key)) {
- if (key != NULL)
+ if (key != NULL && !db->state[db->depth].in_array/*can be inhomogeneous*/)
NOTICE ("curl_json plugin: Found \"%s\", but the configuration expects"
" a map.", buffer);
- cj_cb_inc_array_index (ctx, /* update_key = */ 0);
- return (CJ_CB_CONTINUE);
- } else {
+ cj_cb_inc_array_index (ctx, /* update_key = */ 1);
+ key = db->state[db->depth].key;
+ if (key == NULL) {
+ return (CJ_CB_CONTINUE);
+ }
+ }
+ else
+ {
cj_cb_inc_array_index (ctx, /* update_key = */ 1);
}
memcpy (name, in_name, name_len);
name[name_len] = 0;
- if (c_avl_get (tree, name, (void *) &value) == 0)
- db->state[db->depth].key = value;
+ if (c_avl_get (tree, name, (void *) &value) == 0) {
+ if (CJ_IS_KEY((cj_key_t*)value)) {
+ db->state[db->depth].key = value;
+ }
+ else {
+ db->state[db->depth].tree = (c_avl_tree_t*) value;
+ }
+ }
else if (c_avl_get (tree, CJ_ANY, (void *) &value) == 0)
- db->state[db->depth].key = value;
+ if (CJ_IS_KEY((cj_key_t*)value)) {
+ db->state[db->depth].key = value;
+ }
+ else {
+ db->state[db->depth].tree = (c_avl_tree_t*) value;
+ }
else
db->state[db->depth].key = NULL;
}
{
ERROR ("curl_json plugin: cj_config: "
"Invalid key: %s", ci->key);
+ cj_key_free (key);
return (-1);
}
break;
} /* for (i = 0; i < ci->children_num; i++) */
- while (status == 0)
+ if (status != 0)
{
- if (key->type == NULL)
- {
- WARNING ("curl_json plugin: `Type' missing in `Key' block.");
- status = -1;
- }
+ cj_key_free (key);
+ return (-1);
+ }
- break;
- } /* while (status == 0) */
+ 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 } } }
*/
- if (status == 0)
+ 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 *ptr;
- char *name;
char ent[PATH_MAX];
- c_avl_tree_t *tree;
+ c_avl_tree_t *value;
+ size_t len;
- if (db->tree == NULL)
- db->tree = cj_avl_create();
+ len = ptr - name;
+ if (len == 0)
+ break;
- tree = db->tree;
- name = key->path;
- ptr = key->path;
- if (*ptr == '/')
- ++ptr;
+ len = COUCH_MIN(len, sizeof (ent)-1);
+ sstrncpy (ent, name, len+1);
- name = ptr;
- while (*ptr)
+ if (c_avl_get (tree, ent, (void *) &value) != 0)
{
- if (*ptr == '/')
- {
- c_avl_tree_t *value;
- int 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;
- }
- ++ptr;
- }
- if (*name)
- c_avl_insert (tree, strdup(name), key);
- else
- {
- ERROR ("curl_json plugin: invalid key: %s", key->path);
- status = -1;
+ value = cj_avl_create ();
+ c_avl_insert (tree, strdup (ent), value);
}
+
+ tree = value;
+ name = ptr + 1;
}
+ if (strlen (name) == 0)
+ {
+ ERROR ("curl_json plugin: invalid key: %s", key->path);
+ cj_key_free (key);
+ return (-1);
+ }
+
+ c_avl_insert (tree, strdup (name), key);
return (status);
} /* }}} int cj_config_add_key */
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);
if (db->user != NULL)
{
+#ifdef HAVE_CURLOPT_USERNAME
+ curl_easy_setopt (db->curl, CURLOPT_USERNAME, db->user);
+ curl_easy_setopt (db->curl, CURLOPT_PASSWORD,
+ (db->pass == NULL) ? "" : db->pass);
+#else
size_t credentials_size;
credentials_size = strlen (db->user) + 2;
ssnprintf (db->credentials, credentials_size, "%s:%s",
db->user, (db->pass == NULL) ? "" : db->pass);
curl_easy_setopt (db->curl, CURLOPT_USERPWD, db->credentials);
-
+#endif
+
if (db->digest)
- {
curl_easy_setopt (db->curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
- curl_easy_setopt (db->curl, CURLOPT_USERNAME, db->user);
- curl_easy_setopt (db->curl, CURLOPT_PASSWORD, db->pass);
- }
}
curl_easy_setopt (db->curl, CURLOPT_SSL_VERIFYPEER, (long) db->verify_peer);
if (db->post_body != NULL)
curl_easy_setopt (db->curl, CURLOPT_POSTFIELDS, db->post_body);
+#ifdef HAVE_CURLOPT_TIMEOUT_MS
+ if (db->timeout >= 0)
+ curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) db->timeout);
+ else if (db->interval > 0)
+ curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(db->timeout));
+ else
+ curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
+#endif
+
return (0);
} /* }}} int cj_init_curl */
}
memset (db, 0, sizeof (*db));
+ db->timeout = -1;
+
if (strcasecmp ("URL", ci->key) == 0)
status = cf_util_get_string (ci, &db->url);
else if (strcasecmp ("Sock", ci->key) == 0)
{
ERROR ("curl_json plugin: cj_config: "
"Invalid key: %s", ci->key);
+ cj_free (db);
return (-1);
}
if (status != 0)
status = cf_util_get_string (child, &db->post_body);
else if (strcasecmp ("Key", child->key) == 0)
status = cj_config_add_key (db, child);
+ else if (strcasecmp ("Interval", child->key) == 0)
+ status = cf_util_get_cdtime(child, &db->interval);
+ else if (strcasecmp ("Timeout", child->key) == 0)
+ status = cf_util_get_int (child, &db->timeout);
else
{
WARNING ("curl_json plugin: Option `%s' not allowed here.", child->key);
if (status == 0)
{
user_data_t ud;
- char cb_name[DATA_MAX_NAME_LEN];
+ char *cb_name;
if (db->instance == NULL)
db->instance = strdup("default");
ud.data = (void *) db;
ud.free_func = cj_free;
- ssnprintf (cb_name, sizeof (cb_name), "curl_json-%s-%s",
+ cb_name = ssnprintf_alloc ("curl_json-%s-%s",
db->instance, db->url ? db->url : db->sock);
plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read,
- /* interval = */ NULL, &ud);
+ /* interval = */ db->interval,
+ &ud);
+ sfree (cb_name);
}
else
{
if (key->instance == NULL)
{
- if ((db->depth == 0) || (strcmp ("", db->state[db->depth-1].name) == 0))
- sstrncpy (vl.type_instance, db->state[db->depth].name, sizeof (vl.type_instance));
- else
- ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s",
- db->state[db->depth-1].name, db->state[db->depth].name);
+ int i, len = 0;
+ for (i = 0; i < db->depth; i++)
+ len += ssnprintf(vl.type_instance+len, sizeof(vl.type_instance)-len,
+ i ? "-%s" : "%s", db->state[i+1].name);
}
else
sstrncpy (vl.type_instance, key->instance, sizeof (vl.type_instance));
sstrncpy (vl.plugin_instance, db->instance, sizeof (vl.plugin_instance));
sstrncpy (vl.type, key->type, sizeof (vl.type));
+ if (db->interval > 0)
+ vl.interval = db->interval;
+
plugin_dispatch_values (&vl);
} /* }}} int cj_submit */
return cj_perform (db);
} /* }}} 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);
+} /* }}} 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 : */