Merge pull request #2199 from jaroug/support_attributes_kairosdb
authorRuben Kerkhof <ruben@rubenkerkhof.com>
Sun, 26 Mar 2017 13:36:09 +0000 (15:36 +0200)
committerGitHub <noreply@github.com>
Sun, 26 Mar 2017 13:36:09 +0000 (15:36 +0200)
Add support for 'Attribute' option on KAIROSDB output format

src/collectd.conf.in
src/collectd.conf.pod
src/utils_format_kairosdb.c
src/utils_format_kairosdb.h
src/write_http.c

index a23816d..9508338 100644 (file)
 #              Header "X-Custom-Header: custom_value"
 #              SSLVersion "TLSv1"
 #              Format "Command"
+#              Attribute "key" "value"     # only available for KAIROSDB format
 #              Metrics true
 #              Notifications false
 #              StoreRates false
index 419eb1c..c18f8ef 100644 (file)
@@ -8725,6 +8725,15 @@ create output in the I<JavaScript Object Notation> (JSON). When set to KAIROSDB
 
 Defaults to B<Command>.
 
+=item B<Attribute> I<String> I<String>
+
+Only available for KAIROSDB output format.
+
+Consider the two given strings to be the key and value of an additional tag for
+each metric being sent out.
+
+You can add multiple B<Attribute>.
+
 =item B<Metrics> B<true>|B<false>
 
 Controls whether I<metrics> are POSTed to this location. Defaults to B<true>.
index 1e54b97..2a14f0e 100644 (file)
@@ -181,7 +181,9 @@ static int values_to_kairosdb(char *buffer, size_t buffer_size, /* {{{ */
 
 static int value_list_to_kairosdb(char *buffer, size_t buffer_size, /* {{{ */
                                   const data_set_t *ds, const value_list_t *vl,
-                                  int store_rates) {
+                                  int store_rates,
+                                  char const *const *http_attrs,
+                                  size_t http_attrs_num) {
   char temp[512];
   size_t offset = 0;
   int status;
@@ -231,6 +233,11 @@ static int value_list_to_kairosdb(char *buffer, size_t buffer_size, /* {{{ */
     BUFFER_ADD(", \"tags\":\{");
 
     BUFFER_ADD("\"host\": \"%s\"", vl->host);
+    for (size_t j = 0; j < http_attrs_num; j += 2) {
+      BUFFER_ADD(", \"%s\":", http_attrs[j]);
+      BUFFER_ADD(" \"%s\"", http_attrs[j + 1]);
+    }
+
     if (strlen(vl->plugin_instance))
       BUFFER_ADD_KEYVAL("plugin_instance", vl->plugin_instance);
     BUFFER_ADD_KEYVAL("type", vl->type);
@@ -252,11 +259,13 @@ static int value_list_to_kairosdb(char *buffer, size_t buffer_size, /* {{{ */
 static int format_kairosdb_value_list_nocheck(
     char *buffer, /* {{{ */
     size_t *ret_buffer_fill, size_t *ret_buffer_free, const data_set_t *ds,
-    const value_list_t *vl, int store_rates, size_t temp_size) {
+    const value_list_t *vl, int store_rates, size_t temp_size,
+    char const *const *http_attrs, size_t http_attrs_num) {
   char temp[temp_size];
   int status;
 
-  status = value_list_to_kairosdb(temp, sizeof(temp), ds, vl, store_rates);
+  status = value_list_to_kairosdb(temp, sizeof(temp), ds, vl, store_rates,
+                                  http_attrs, http_attrs_num);
   if (status != 0)
     return (status);
   temp_size = strlen(temp);
@@ -324,7 +333,8 @@ int format_kairosdb_finalize(char *buffer, /* {{{ */
 int format_kairosdb_value_list(char *buffer, /* {{{ */
                                size_t *ret_buffer_fill, size_t *ret_buffer_free,
                                const data_set_t *ds, const value_list_t *vl,
-                               int store_rates) {
+                               int store_rates, char const *const *http_attrs,
+                               size_t http_attrs_num) {
   if ((buffer == NULL) || (ret_buffer_fill == NULL) ||
       (ret_buffer_free == NULL) || (ds == NULL) || (vl == NULL))
     return (-EINVAL);
@@ -334,5 +344,7 @@ int format_kairosdb_value_list(char *buffer, /* {{{ */
 
   return (format_kairosdb_value_list_nocheck(
       buffer, ret_buffer_fill, ret_buffer_free, ds, vl, store_rates,
-      (*ret_buffer_free) - 2));
+      (*ret_buffer_free) - 2, http_attrs, http_attrs_num));
 } /* }}} int format_kairosdb_value_list */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
index 9174318..b6aa39d 100644 (file)
@@ -39,7 +39,9 @@ int format_kairosdb_initialize(char *buffer, size_t *ret_buffer_fill,
                                size_t *ret_buffer_free);
 int format_kairosdb_value_list(char *buffer, size_t *ret_buffer_fill,
                                size_t *ret_buffer_free, const data_set_t *ds,
-                               const value_list_t *vl, int store_rates);
+                               const value_list_t *vl, int store_rates,
+                               char const *const *http_attrs,
+                               size_t http_attrs_num);
 int format_kairosdb_finalize(char *buffer, size_t *ret_buffer_fill,
                              size_t *ret_buffer_free);
 
index c33ab54..c6efe07 100644 (file)
@@ -81,6 +81,9 @@ struct wh_callback_s {
 };
 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;
@@ -468,9 +471,9 @@ static int wh_write_kairosdb(const data_set_t *ds,
     }
   }
 
-  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);
   if (status == -ENOMEM) {
     status = wh_flush_nolock(/* timeout = */ 0, cb);
     if (status != 0) {
@@ -479,9 +482,9 @@ static int wh_write_kairosdb(const data_set_t *ds,
       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);
   }
   if (status != 0) {
     pthread_mutex_unlock(&cb->send_lock);
@@ -703,7 +706,34 @@ static int wh_config_node(oconfig_item_t *ci) /* {{{ */
       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 {
       ERROR("write_http plugin: Invalid configuration "
             "option: %s.",
             child->key);