]> git.ipfire.org Git - thirdparty/collectd.git/commitdiff
src/daemon/metric.[ch]: Implement metric_family_append().
authorFlorian Forster <octo@google.com>
Tue, 7 Jul 2020 07:52:57 +0000 (09:52 +0200)
committerFlorian Forster <octo@google.com>
Tue, 21 Jul 2020 15:30:08 +0000 (17:30 +0200)
src/daemon/metric.c
src/daemon/metric.h
src/daemon/metric_test.c

index 3efa5de600619dd030191040520671c1bf654acd..60625a9f0157905bfcebe029b1f1d5be3bad7ea3 100644 (file)
@@ -372,6 +372,39 @@ int metric_family_metric_append(metric_family_t *fam, metric_t m) {
   return metric_list_add(&fam->metric, m);
 }
 
+int metric_family_append(metric_family_t *fam, char const *lname,
+                         char const *lvalue, value_t v, metric_t const *templ) {
+  if ((fam == NULL) || ((lname == NULL) != (lvalue == NULL))) {
+    return EINVAL;
+  }
+
+  metric_t m = {
+      .family = fam,
+      .value = v,
+  };
+  if (templ != NULL) {
+    int status = label_set_clone(&m.label, templ->label);
+    if (status != 0) {
+      return status;
+    }
+
+    m.time = templ->time;
+    m.interval = templ->interval;
+    m.meta = meta_data_clone(templ->meta);
+  }
+
+  if (lname != NULL) {
+    int status = metric_label_set(&m, lname, lvalue);
+    if (status != 0) {
+      return status;
+    }
+  }
+
+  int status = metric_family_metric_append(fam, m);
+  metric_reset(&m);
+  return status;
+}
+
 int metric_family_metric_reset(metric_family_t *fam) {
   if (fam == NULL) {
     return EINVAL;
index 66d36380d63bc8ed001809d40eadae6db9178bf3..f849a3703e4b2434f2996ffc63ff2b05bf3ec55a 100644 (file)
@@ -149,6 +149,18 @@ struct metric_family_s {
  * allocates memory which must be freed using metric_family_metric_reset. */
 int metric_family_metric_append(metric_family_t *fam, metric_t m);
 
+/* metric_family_append constructs a new metric_t and appends it to fam. It is
+ * a convenience function that is funcitonally approximately equivalent to the
+ * following code, but without modifying templ:
+ *
+ *   metric_t m = *templ;
+ *   m.value = v;
+ *   metric_label_set(&m, lname, lvalue);
+ *   metric_family_metric_append(fam, m);
+ */
+int metric_family_append(metric_family_t *fam, char const *lname,
+                         char const *lvalue, value_t v, metric_t const *templ);
+
 /* metric_family_metric_reset frees all metrics in the metric family and
  * resets the count to zero. */
 int metric_family_metric_reset(metric_family_t *fam);
index da7b4731b1211d3cb5689bad7a7c5599d8074f79..12816204609d74f13584b9aeaa3f738a3e3bee27 100644 (file)
@@ -159,9 +159,111 @@ DEF_TEST(metric_identity) {
   return 0;
 }
 
+DEF_TEST(metric_family_append) {
+  struct {
+    char const *lname;
+    char const *lvalue;
+    gauge_t v;
+    metric_t *templ;
+    int want_err;
+    label_t *want_labels;
+    size_t want_labels_num;
+    gauge_t want_value;
+    cdtime_t want_time;
+    cdtime_t want_interval;
+  } cases[] = {
+      {
+          .v = 42,
+          .want_value = 42,
+      },
+      {
+          .lname = "type",
+          .lvalue = "test",
+          .v = 42,
+          .want_labels =
+              (label_t[]){
+                  {"type", "test"},
+              },
+          .want_labels_num = 1,
+          .want_value = 42,
+      },
+      {
+          .v = 42,
+          .templ =
+              &(metric_t){
+                  .time = TIME_T_TO_CDTIME_T(1594107920),
+              },
+          .want_value = 42,
+          .want_time = TIME_T_TO_CDTIME_T(1594107920),
+      },
+      {
+          .v = 42,
+          .templ =
+              &(metric_t){
+                  .interval = TIME_T_TO_CDTIME_T(10),
+              },
+          .want_value = 42,
+          .want_interval = TIME_T_TO_CDTIME_T(10),
+      },
+      {
+          .lname = "type",
+          .lvalue = "test",
+          .v = 42,
+          .templ =
+              &(metric_t){
+                  .label =
+                      {
+                          .ptr = &(label_pair_t){"common", "label"},
+                          .num = 1,
+                      },
+              },
+          .want_labels =
+              (label_t[]){
+                  {"common", "label"},
+                  {"type", "test"},
+              },
+          .want_labels_num = 2,
+          .want_value = 42,
+      },
+  };
+
+  for (size_t i = 0; i < (sizeof(cases) / sizeof(cases[0])); i++) {
+    metric_family_t fam = {
+        .name = "test_total",
+        .type = METRIC_TYPE_GAUGE,
+    };
+
+    EXPECT_EQ_INT(cases[i].want_err,
+                  metric_family_append(&fam, cases[i].lname, cases[i].lvalue,
+                                       (value_t){.gauge = cases[i].v},
+                                       cases[i].templ));
+    if (cases[i].want_err != 0) {
+      continue;
+    }
+
+    EXPECT_EQ_INT(1, fam.metric.num);
+    metric_t const *m = fam.metric.ptr;
+
+    EXPECT_EQ_INT(cases[i].want_labels_num, m->label.num);
+    for (size_t j = 0; j < cases[i].want_labels_num; j++) {
+      EXPECT_EQ_STR(cases[i].want_labels[j].value,
+                    metric_label_get(m, cases[i].want_labels[j].name));
+    }
+
+    EXPECT_EQ_DOUBLE(cases[i].want_value, m->value.gauge);
+    EXPECT_EQ_UINT64(cases[i].want_time, m->time);
+    EXPECT_EQ_UINT64(cases[i].want_interval, m->interval);
+
+    metric_family_metric_reset(&fam);
+  }
+
+  return 0;
+}
+
 int main(void) {
   RUN_TEST(metric_label_set);
   RUN_TEST(metric_identity);
+  RUN_TEST(metric_family_append);
 
   END_TEST;
 }