Merge branch 'collectd-5.8'
[collectd.git] / src / utils_format_graphite.c
index 4f509f4..de3f0c2 100644 (file)
@@ -46,11 +46,11 @@ static int gr_format_values(char *ret, size_t ret_len, int ds_num,
 
 #define BUFFER_ADD(...)                                                        \
   do {                                                                         \
-    status = ssnprintf(ret + offset, ret_len - offset, __VA_ARGS__);           \
+    status = snprintf(ret + offset, ret_len - offset, __VA_ARGS__);            \
     if (status < 1) {                                                          \
-      return (-1);                                                             \
+      return -1;                                                               \
     } else if (((size_t)status) >= (ret_len - offset)) {                       \
-      return (-1);                                                             \
+      return -1;                                                               \
     } else                                                                     \
       offset += ((size_t)status);                                              \
   } while (0)
@@ -60,24 +60,24 @@ 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);
-    return (-1);
+    P_ERROR("gr_format_values: Unknown data source type: %i",
+            ds->ds[ds_num].type);
+    return -1;
   }
 
 #undef BUFFER_ADD
 
-  return (0);
+  return 0;
 }
 
 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);
@@ -131,9 +211,9 @@ static int gr_format_name(char *ret, int ret_len, value_list_t const *vl,
                       sizeof(n_type_instance), escape_char, preserve_separator);
 
   if (n_plugin_instance[0] != '\0')
-    ssnprintf(tmp_plugin, sizeof(tmp_plugin), "%s%c%s", n_plugin,
-              (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
-              n_plugin_instance);
+    snprintf(tmp_plugin, sizeof(tmp_plugin), "%s%c%s", n_plugin,
+             (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
+             n_plugin_instance);
   else
     sstrncpy(tmp_plugin, n_plugin, sizeof(tmp_plugin));
 
@@ -141,9 +221,9 @@ static int gr_format_name(char *ret, int ret_len, value_list_t const *vl,
     if ((flags & GRAPHITE_DROP_DUPE_FIELDS) && strcmp(n_plugin, n_type) == 0)
       sstrncpy(tmp_type, n_type_instance, sizeof(tmp_type));
     else
-      ssnprintf(tmp_type, sizeof(tmp_type), "%s%c%s", n_type,
-                (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
-                n_type_instance);
+      snprintf(tmp_type, sizeof(tmp_type), "%s%c%s", n_type,
+               (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
+               n_type_instance);
   } else
     sstrncpy(tmp_type, n_type, sizeof(tmp_type));
 
@@ -152,16 +232,16 @@ static int gr_format_name(char *ret, int ret_len, value_list_t const *vl,
   if (ds_name != NULL) {
     if ((flags & GRAPHITE_DROP_DUPE_FIELDS) &&
         strcmp(tmp_plugin, tmp_type) == 0)
-      ssnprintf(ret, ret_len, "%s%s%s.%s.%s", prefix, n_host, postfix,
-                tmp_plugin, ds_name);
+      snprintf(ret, ret_len, "%s%s%s.%s.%s", prefix, n_host, postfix,
+               tmp_plugin, ds_name);
     else
-      ssnprintf(ret, ret_len, "%s%s%s.%s.%s.%s", prefix, n_host, postfix,
-                tmp_plugin, tmp_type, ds_name);
+      snprintf(ret, ret_len, "%s%s%s.%s.%s.%s", prefix, n_host, postfix,
+               tmp_plugin, tmp_type, ds_name);
   } else
-    ssnprintf(ret, ret_len, "%s%s%s.%s.%s", prefix, n_host, postfix, tmp_plugin,
-              tmp_type);
+    snprintf(ret, ret_len, "%s%s%s.%s.%s", prefix, n_host, postfix, tmp_plugin,
+             tmp_type);
 
-  return (0);
+  return 0;
 }
 
 static void escape_graphite_string(char *buffer, char escape_char) {
@@ -180,8 +260,13 @@ int format_graphite(char *buffer, size_t buffer_size, data_set_t const *ds,
   int buffer_pos = 0;
 
   gauge_t *rates = NULL;
-  if (flags & GRAPHITE_STORE_RATES)
+  if (flags & GRAPHITE_STORE_RATES) {
     rates = uc_get_rate(ds, vl);
+    if (rates == NULL) {
+      P_ERROR("format_graphite: error with uc_get_rate");
+      return -1;
+    }
+  }
 
   for (size_t i = 0; i < ds->ds_num; i++) {
     char const *ds_name = NULL;
@@ -194,48 +279,57 @@ 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);
+      return status;
     }
 
     /* Compute the graphite command */
     message_len =
-        (size_t)ssnprintf(message, sizeof(message), "%s %s %u\r\n", key, values,
-                          (unsigned int)CDTIME_T_TO_TIME_T(vl->time));
+        (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);
+      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);
+      return -ENOMEM;
     }
     memcpy((void *)(buffer + buffer_pos), message, message_len);
     buffer_pos += message_len;
     buffer[buffer_pos] = '\0';
   }
   sfree(rates);
-  return (status);
+  return status;
 } /* int format_graphite */
-
-/* vim: set sw=2 sts=2 et fdm=marker : */