Merge branch 'collectd-5.8'
[collectd.git] / src / utils_format_graphite.c
index 87cead1..de3f0c2 100644 (file)
@@ -60,14 +60,14 @@ static int gr_format_values(char *ret, size_t ret_len, int ds_num,
   else if (rates != NULL)
     BUFFER_ADD("%f", rates[ds_num]);
   else if (ds->ds[ds_num].type == DS_TYPE_COUNTER)
-    BUFFER_ADD("%llu", vl->values[ds_num].counter);
+    BUFFER_ADD("%" PRIu64, (uint64_t)vl->values[ds_num].counter);
   else if (ds->ds[ds_num].type == DS_TYPE_DERIVE)
     BUFFER_ADD("%" PRIi64, vl->values[ds_num].derive);
   else if (ds->ds[ds_num].type == DS_TYPE_ABSOLUTE)
     BUFFER_ADD("%" PRIu64, vl->values[ds_num].absolute);
   else {
-    ERROR("gr_format_values plugin: Unknown data source type: %i",
-          ds->ds[ds_num].type);
+    P_ERROR("gr_format_values: Unknown data source type: %i",
+            ds->ds[ds_num].type);
     return -1;
   }
 
@@ -77,7 +77,7 @@ static int gr_format_values(char *ret, size_t ret_len, int ds_num,
 }
 
 static void gr_copy_escape_part(char *dst, const char *src, size_t dst_len,
-                                char escape_char, _Bool preserve_separator) {
+                                char escape_char, bool preserve_separator) {
   memset(dst, 0, dst_len);
 
   if (src == NULL)
@@ -97,6 +97,86 @@ static void gr_copy_escape_part(char *dst, const char *src, size_t dst_len,
   }
 }
 
+static int gr_format_name_tagged(char *ret, int ret_len, value_list_t const *vl,
+                                 char const *ds_name, char const *prefix,
+                                 char const *postfix, char const escape_char,
+                                 unsigned int flags) {
+  char n_host[DATA_MAX_NAME_LEN];
+  char n_plugin[DATA_MAX_NAME_LEN];
+  char n_plugin_instance[DATA_MAX_NAME_LEN];
+  char n_type[DATA_MAX_NAME_LEN];
+  char n_type_instance[DATA_MAX_NAME_LEN];
+
+  char tmp_plugin[DATA_MAX_NAME_LEN + 8];
+  char tmp_plugin_instance[DATA_MAX_NAME_LEN + 17];
+  char tmp_type[DATA_MAX_NAME_LEN + 6];
+  char tmp_type_instance[DATA_MAX_NAME_LEN + 15];
+  char tmp_metric[3 * DATA_MAX_NAME_LEN + 2];
+  char tmp_ds_name[DATA_MAX_NAME_LEN + 9];
+
+  if (prefix == NULL)
+    prefix = "";
+
+  if (postfix == NULL)
+    postfix = "";
+
+  gr_copy_escape_part(n_host, vl->host, sizeof(n_host), escape_char, 1);
+  gr_copy_escape_part(n_plugin, vl->plugin, sizeof(n_plugin), escape_char, 1);
+  gr_copy_escape_part(n_plugin_instance, vl->plugin_instance,
+                      sizeof(n_plugin_instance), escape_char, 1);
+  gr_copy_escape_part(n_type, vl->type, sizeof(n_type), escape_char, 1);
+  gr_copy_escape_part(n_type_instance, vl->type_instance,
+                      sizeof(n_type_instance), escape_char, 1);
+
+  snprintf(tmp_plugin, sizeof(tmp_plugin), ";plugin=%s", n_plugin);
+
+  if (n_plugin_instance[0] != '\0')
+    snprintf(tmp_plugin_instance, sizeof(tmp_plugin_instance),
+             ";plugin_instance=%s", n_plugin_instance);
+  else
+    tmp_plugin_instance[0] = '\0';
+
+  if (!(flags & GRAPHITE_DROP_DUPE_FIELDS) || strcmp(n_plugin, n_type) != 0)
+    snprintf(tmp_type, sizeof(tmp_type), ";type=%s", n_type);
+  else
+    tmp_type[0] = '\0';
+
+  if (n_type_instance[0] != '\0') {
+    if (!(flags & GRAPHITE_DROP_DUPE_FIELDS) ||
+        strcmp(n_plugin_instance, n_type_instance) != 0)
+      snprintf(tmp_type_instance, sizeof(tmp_type_instance),
+               ";type_instance=%s", n_type_instance);
+    else
+      tmp_type_instance[0] = '\0';
+  } else
+    tmp_type_instance[0] = '\0';
+
+  /* Assert always_append_ds -> ds_name */
+  assert(!(flags & GRAPHITE_ALWAYS_APPEND_DS) || (ds_name != NULL));
+  if (ds_name != NULL) {
+    snprintf(tmp_ds_name, sizeof(tmp_ds_name), ";ds_name=%s", ds_name);
+
+    if ((flags & GRAPHITE_DROP_DUPE_FIELDS) && strcmp(n_plugin, n_type) == 0)
+      snprintf(tmp_metric, sizeof(tmp_metric), "%s.%s", n_plugin, ds_name);
+    else
+      snprintf(tmp_metric, sizeof(tmp_metric), "%s.%s.%s", n_plugin, n_type,
+               ds_name);
+  } else {
+    tmp_ds_name[0] = '\0';
+
+    if ((flags & GRAPHITE_DROP_DUPE_FIELDS) && strcmp(n_plugin, n_type) == 0)
+      snprintf(tmp_metric, sizeof(tmp_metric), "%s", n_plugin);
+    else
+      snprintf(tmp_metric, sizeof(tmp_metric), "%s.%s", n_plugin, n_type);
+  }
+
+  snprintf(ret, ret_len, "%s%s%s;host=%s%s%s%s%s%s", prefix, tmp_metric,
+           postfix, n_host, tmp_plugin, tmp_plugin_instance, tmp_type,
+           tmp_type_instance, tmp_ds_name);
+
+  return 0;
+}
+
 static int gr_format_name(char *ret, int ret_len, value_list_t const *vl,
                           char const *ds_name, char const *prefix,
                           char const *postfix, char const escape_char,
@@ -116,7 +196,7 @@ static int gr_format_name(char *ret, int ret_len, value_list_t const *vl,
   if (postfix == NULL)
     postfix = "";
 
-  _Bool preserve_separator = (flags & GRAPHITE_PRESERVE_SEPARATOR) ? 1 : 0;
+  bool preserve_separator = (flags & GRAPHITE_PRESERVE_SEPARATOR);
 
   gr_copy_escape_part(n_host, vl->host, sizeof(n_host), escape_char,
                       preserve_separator);
@@ -183,7 +263,7 @@ int format_graphite(char *buffer, size_t buffer_size, data_set_t const *ds,
   if (flags & GRAPHITE_STORE_RATES) {
     rates = uc_get_rate(ds, vl);
     if (rates == NULL) {
-      ERROR("format_graphite: error with uc_get_rate");
+      P_ERROR("format_graphite: error with uc_get_rate");
       return -1;
     }
   }
@@ -199,20 +279,31 @@ int format_graphite(char *buffer, size_t buffer_size, data_set_t const *ds,
       ds_name = ds->ds[i].name;
 
     /* Copy the identifier to `key' and escape it. */
-    status = gr_format_name(key, sizeof(key), vl, ds_name, prefix, postfix,
-                            escape_char, flags);
-    if (status != 0) {
-      ERROR("format_graphite: error with gr_format_name");
-      sfree(rates);
-      return status;
+    if (flags & GRAPHITE_USE_TAGS) {
+      status = gr_format_name_tagged(key, sizeof(key), vl, ds_name, prefix,
+                                     postfix, escape_char, flags);
+      if (status != 0) {
+        P_ERROR("format_graphite: error with gr_format_name_tagged");
+        sfree(rates);
+        return status;
+      }
+    } else {
+      status = gr_format_name(key, sizeof(key), vl, ds_name, prefix, postfix,
+                              escape_char, flags);
+      if (status != 0) {
+        P_ERROR("format_graphite: error with gr_format_name");
+        sfree(rates);
+        return status;
+      }
     }
 
     escape_graphite_string(key, escape_char);
+
     /* Convert the values to an ASCII representation and put that into
      * `values'. */
     status = gr_format_values(values, sizeof(values), i, ds, vl, rates);
     if (status != 0) {
-      ERROR("format_graphite: error with gr_format_values");
+      P_ERROR("format_graphite: error with gr_format_values");
       sfree(rates);
       return status;
     }
@@ -222,16 +313,16 @@ int format_graphite(char *buffer, size_t buffer_size, data_set_t const *ds,
         (size_t)snprintf(message, sizeof(message), "%s %s %u\r\n", key, values,
                          (unsigned int)CDTIME_T_TO_TIME_T(vl->time));
     if (message_len >= sizeof(message)) {
-      ERROR("format_graphite: message buffer too small: "
-            "Need %zu bytes.",
-            message_len + 1);
+      P_ERROR("format_graphite: message buffer too small: "
+              "Need %" PRIsz " bytes.",
+              message_len + 1);
       sfree(rates);
       return -ENOMEM;
     }
 
     /* Append it in case we got multiple data set */
     if ((buffer_pos + message_len) >= buffer_size) {
-      ERROR("format_graphite: target buffer too small");
+      P_ERROR("format_graphite: target buffer too small");
       sfree(rates);
       return -ENOMEM;
     }