Merge branch 'collectd-5.4' into collectd-5.5
[collectd.git] / src / statsd.c
index 327b8db..5b0bdd6 100644 (file)
@@ -1,19 +1,24 @@
 /**
  * collectd - src/statsd.c
- *
  * Copyright (C) 2013       Florian octo Forster
  *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
  *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
  *   Florian octo Forster <octo at collectd.org>
@@ -190,6 +195,35 @@ static int statsd_metric_add (char const *name, double delta, /* {{{ */
   return (0);
 } /* }}} int statsd_metric_add */
 
+static void statsd_metric_free (statsd_metric_t *metric) /* {{{ */
+{
+  if (metric == NULL)
+    return;
+
+  if (metric->latency != NULL)
+  {
+    latency_counter_destroy (metric->latency);
+    metric->latency = NULL;
+  }
+
+  if (metric->set != NULL)
+  {
+    void *key;
+    void *value;
+
+    while (c_avl_pick (metric->set, &key, &value) == 0)
+    {
+      sfree (key);
+      assert (value == NULL);
+    }
+
+    c_avl_destroy (metric->set);
+    metric->set = NULL;
+  }
+
+  sfree (metric);
+} /* }}} void statsd_metric_free */
+
 static int statsd_parse_value (char const *str, value_t *ret_value) /* {{{ */
 {
   char *endptr = NULL;
@@ -748,39 +782,42 @@ static int statsd_metric_submit_unsafe (char const *name, /* {{{ */
   else if (metric->type == STATSD_TIMER)
   {
     size_t i;
+    _Bool have_events = (metric->updates_num > 0);
 
-    if (metric->updates_num == 0)
-      return (0);
-
+    /* Make sure all timer metrics share the *same* timestamp. */
     vl.time = cdtime ();
 
     ssnprintf (vl.type_instance, sizeof (vl.type_instance),
         "%s-average", name);
-    values[0].gauge = CDTIME_T_TO_DOUBLE (
-        latency_counter_get_average (metric->latency));
+    values[0].gauge = have_events
+      ? CDTIME_T_TO_DOUBLE (latency_counter_get_average (metric->latency))
+      : NAN;
     plugin_dispatch_values (&vl);
 
     if (conf_timer_lower) {
       ssnprintf (vl.type_instance, sizeof (vl.type_instance),
           "%s-lower", name);
-      values[0].gauge = CDTIME_T_TO_DOUBLE (
-          latency_counter_get_min (metric->latency));
+      values[0].gauge = have_events
+        ? CDTIME_T_TO_DOUBLE (latency_counter_get_min (metric->latency))
+        : NAN;
       plugin_dispatch_values (&vl);
     }
 
     if (conf_timer_upper) {
       ssnprintf (vl.type_instance, sizeof (vl.type_instance),
           "%s-upper", name);
-      values[0].gauge = CDTIME_T_TO_DOUBLE (
-          latency_counter_get_max (metric->latency));
+      values[0].gauge = have_events
+        ? CDTIME_T_TO_DOUBLE (latency_counter_get_max (metric->latency))
+        : NAN;
       plugin_dispatch_values (&vl);
     }
 
     if (conf_timer_sum) {
       ssnprintf (vl.type_instance, sizeof (vl.type_instance),
           "%s-sum", name);
-      values[0].gauge = CDTIME_T_TO_DOUBLE (
-          latency_counter_get_sum (metric->latency));
+      values[0].gauge = have_events
+        ? CDTIME_T_TO_DOUBLE (latency_counter_get_sum (metric->latency))
+        : NAN;
       plugin_dispatch_values (&vl);
     }
 
@@ -788,9 +825,9 @@ static int statsd_metric_submit_unsafe (char const *name, /* {{{ */
     {
       ssnprintf (vl.type_instance, sizeof (vl.type_instance),
           "%s-percentile-%.0f", name, conf_timer_percentile[i]);
-      values[0].gauge = CDTIME_T_TO_DOUBLE (
-          latency_counter_get_percentile (
-            metric->latency, conf_timer_percentile[i]));
+      values[0].gauge = have_events
+        ? CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (metric->latency, conf_timer_percentile[i]))
+        : NAN;
       plugin_dispatch_values (&vl);
     }
 
@@ -877,7 +914,7 @@ static int statsd_read (void) /* {{{ */
     }
 
     sfree (name);
-    sfree (metric);
+    statsd_metric_free (metric);
   }
 
   pthread_mutex_unlock (&metrics_lock);