]> git.ipfire.org Git - thirdparty/collectd.git/commitdiff
format_json: Use metric_t internally
authorFlorian Forster <octo@google.com>
Fri, 17 Jul 2020 10:27:23 +0000 (12:27 +0200)
committerFlorian Forster <octo@google.com>
Wed, 29 Jul 2020 11:37:32 +0000 (13:37 +0200)
This is a WIP

This commit is where the major transform takes palce; the internal
representation is changed, and the read plugins use that indirectly
when they submit a value list transparently.

The baromerter read plugin has been converted to using metric_t
representation natively.

The write plugins have to be adapted to use these new single data
source metrics.

Signed-off-by: Manoj Srivastava <srivasta@google.com>
Change-Id: I9bdeaa59de5c58d11c0ae0e7b55d68d9e4d77fa1

# Conflicts:
# src/daemon/metrics_list_test.c

src/utils/format_json/format_json.c
src/utils/format_json/format_json.h

index ee40db7b758c284eeb6769d7907c4d5b3eabd64d..32f35e8730d5ae77b7a6123ebb2ac4436221a33e 100644 (file)
@@ -22,6 +22,7 @@
  *
  * Authors:
  *   Florian octo Forster <octo at collectd.org>
+ *   Manoj Srivastava <srivasta at google.com>
  **/
 
 #include "collectd.h"
@@ -29,6 +30,7 @@
 #include "utils/format_json/format_json.h"
 
 #include "plugin.h"
+#include "utils/avltree/avltree.h"
 #include "utils/common/common.h"
 #include "utils_cache.h"
 
@@ -374,6 +376,131 @@ static int value_list_to_json(char *buffer, size_t buffer_size, /* {{{ */
   return 0;
 } /* }}} int value_list_to_json */
 
+
+int format_json_metric(char *buffer_p, size_t *ret_buffer_fill, /* {{{ */
+                       size_t *ret_buffer_free, const metric_t *metric_p,
+                       int store_rates) {
+  char temp[1024];
+  gauge_t rate = -1;
+  int status = 0;
+
+  if ((buffer_p == NULL) || (ret_buffer_fill == NULL) ||
+      (ret_buffer_free == NULL) || (metric_p == NULL) ||
+      (metric_p->identity == NULL) || (metric_p->ds == NULL))
+    return -EINVAL;
+
+  if (*ret_buffer_free < 3)
+    return -ENOMEM;
+
+  /* Respect high water marks and fere size */
+  char *buffer = buffer_p + (*ret_buffer_fill);
+  size_t buffer_size = *ret_buffer_free;
+  size_t offset = 0;
+
+#define BUFFER_ADD(...)                                                        \
+  do {                                                                         \
+    status = snprintf(buffer + offset, buffer_size - offset, __VA_ARGS__);     \
+    if (status < 1)                                                            \
+      return -1;                                                               \
+    else if (((size_t)status) >= (buffer_size - offset))                       \
+      return -ENOMEM;                                                          \
+    else                                                                       \
+      offset += ((size_t)status);                                              \
+  } while (0)
+
+#define BUFFER_ADD_KEYVAL(key, value)                                          \
+  do {                                                                         \
+    status = json_escape_string(temp, sizeof(temp), (value));                  \
+    if (status != 0)                                                           \
+      return status;                                                           \
+    BUFFER_ADD(",\"%s\":%s", (key), temp);                                     \
+  } while (0)
+
+  /* Designed to be called multiple times, as when adding metrics from a
+     metrics_lisat_t object. When finalizing, the initial leading comma
+     will be replaced by a [ */
+  BUFFER_ADD(",{");
+  BUFFER_ADD_KEYVAL("name", metric_p->identity->name);
+  if (metric_p->value_ds_type == DS_TYPE_GAUGE) {
+    if (isfinite(metric_p->value.gauge))
+      BUFFER_ADD(JSON_GAUGE_FORMAT, metric_p->value.gauge);
+    else
+      BUFFER_ADD("null");
+  } else if (store_rates) {
+    if (rate == -1)
+      status = uc_get_rate(metric_p, &rate);
+    if (status != 0) {
+      WARNING("utils_format_json: uc_get_rate failed.");
+      buffer_p[*ret_buffer_fill] = '0';
+      return -1;
+    }
+
+    if (isfinite(rate))
+      BUFFER_ADD(JSON_GAUGE_FORMAT, rate);
+    else
+      BUFFER_ADD("null");
+  } else if (metric_p->value_ds_type == DS_TYPE_COUNTER)
+    BUFFER_ADD("%" PRIu64, (uint64_t)metric_p->value.counter);
+  else if (metric_p->value_ds_type == DS_TYPE_DERIVE)
+    BUFFER_ADD("%" PRIi64, metric_p->value.derive);
+  else if (metric_p->value_ds_type == DS_TYPE_ABSOLUTE)
+    BUFFER_ADD("%" PRIu64, metric_p->value.absolute);
+  else {
+    ERROR("format_json: Unknown data source type: %i", metric_p->value_ds_type);
+    buffer_p[*ret_buffer_fill] = '0';
+    return -1;
+  }
+
+  BUFFER_ADD(",\"time\":%.3f", CDTIME_T_TO_DOUBLE(metric_p->time));
+  BUFFER_ADD(",\"interval\":%.3f", CDTIME_T_TO_DOUBLE(metric_p->interval));
+  BUFFER_ADD_KEYVAL("plugin", metric_p->plugin);
+  BUFFER_ADD_KEYVAL("type", metric_p->type);
+  BUFFER_ADD_KEYVAL("dsname", metric_p->ds->name);
+  BUFFER_ADD_KEYVAL("dstype", DS_TYPE_TO_STRING(metric_p->value_ds_type));
+
+  if (metric_p->identity->root_p != NULL) {
+    c_avl_iterator_t *iter_p = c_avl_get_iterator(metric_p->identity->root_p);
+    if (iter_p != NULL) {
+      char *key_p = NULL;
+      char *value_p = NULL;
+      BUFFER_ADD("\"labels\":{");
+      while ((c_avl_iterator_next(iter_p, (void **)&key_p,
+                                  (void **)&value_p)) == 0) {
+        if ((key_p != NULL) && (value_p != NULL)) {
+          BUFFER_ADD_KEYVAL(key_p, value_p);
+        }
+      }
+      BUFFER_ADD("},");
+      c_avl_iterator_destroy(iter_p);
+    }
+  }
+
+  if (metric_p->meta != NULL) {
+    char meta_buffer[buffer_size];
+    memset(meta_buffer, 0, sizeof(meta_buffer));
+    status = meta_data_to_json(meta_buffer, sizeof(meta_buffer),
+                               metric_p->meta->meta);
+    if (status != 0) {
+      buffer_p[*ret_buffer_fill] = '0';
+      return status;
+    }
+
+    BUFFER_ADD(",\"meta\":%s", meta_buffer);
+  } /* if (vl->meta != NULL) */
+
+  BUFFER_ADD("}");
+
+#undef BUFFER_ADD_KEYVAL
+#undef BUFFER_ADD
+
+  /* Update hihg water mark and free size */
+  (*ret_buffer_fill) += offset;
+  (*ret_buffer_free) -= offset;
+
+  return 0;
+} /* }}} */
+
+
 static int format_json_value_list_nocheck(char *buffer, /* {{{ */
                                           size_t *ret_buffer_fill,
                                           size_t *ret_buffer_free,
index d3d02160e58562ec84b409a059d2f60209a8766e..a59ed6237a64f4a0af1448f35fc5ba977490b6b9 100644 (file)
@@ -40,6 +40,9 @@ int format_json_initialize(char *buffer, size_t *ret_buffer_fill,
 int format_json_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 format_json_metric(char *buffer_p, size_t *ret_buffer_fill,
+                       size_t *ret_buffer_free, const metric_t *metric_p,
+                       int store_rates);
 int format_json_finalize(char *buffer, size_t *ret_buffer_fill,
                          size_t *ret_buffer_free);
 int format_json_notification(char *buffer, size_t buffer_size,