X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fstatsd.c;h=ba8901b9e842ef494e2789190ee3a9046f03e05a;hb=961ead7ebf855bcb53728734c828378c187f23ce;hp=72a7779b929b11a1577b75e6276bc658ac1ee054;hpb=06af7097ff0c9f97667774ab658e560f0950a23f;p=collectd.git diff --git a/src/statsd.c b/src/statsd.c index 72a7779b..ba8901b9 100644 --- a/src/statsd.c +++ b/src/statsd.c @@ -34,6 +34,11 @@ #include #include +/* AIX doesn't have MSG_DONTWAIT */ +#ifndef MSG_DONTWAIT +# define MSG_DONTWAIT MSG_NONBLOCK +#endif + #ifndef STATSD_DEFAULT_NODE # define STATSD_DEFAULT_NODE NULL #endif @@ -185,6 +190,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; @@ -245,19 +279,35 @@ static int statsd_handle_gauge (char const *name, /* {{{ */ } /* }}} int statsd_handle_gauge */ static int statsd_handle_timer (char const *name, /* {{{ */ - char const *value_str) + char const *value_str, + char const *extra) { statsd_metric_t *metric; value_t value_ms; + value_t scale; cdtime_t value; int status; + if ((extra != NULL) && (extra[0] != '@')) + return (-1); + + scale.gauge = 1.0; + if (extra != NULL) + { + status = statsd_parse_value (extra + 1, &scale); + if (status != 0) + return (status); + + if (!isfinite (scale.gauge) || (scale.gauge <= 0.0) || (scale.gauge > 1.0)) + return (-1); + } + value_ms.derive = 0; status = statsd_parse_value (value_str, &value_ms); if (status != 0) return (status); - value = MS_TO_CDTIME_T (value_ms.gauge); + value = MS_TO_CDTIME_T (value_ms.gauge / scale.gauge); pthread_mutex_lock (&metrics_lock); @@ -367,15 +417,15 @@ static int statsd_parse_line (char *buffer) /* {{{ */ if (strcmp ("c", type) == 0) return (statsd_handle_counter (name, value, extra)); + else if (strcmp ("ms", type) == 0) + return (statsd_handle_timer (name, value, extra)); - /* extra is only valid for counters */ + /* extra is only valid for counters and timers */ if (extra != NULL) return (-1); if (strcmp ("g", type) == 0) return (statsd_handle_gauge (name, value)); - else if (strcmp ("ms", type) == 0) - return (statsd_handle_timer (name, value)); else if (strcmp ("s", type) == 0) return (statsd_handle_set (name, value)); else @@ -507,6 +557,7 @@ static int statsd_network_init (struct pollfd **ret_fds, /* {{{ */ if (tmp == NULL) { ERROR ("statsd plugin: realloc failed."); + close (fd); continue; } fds = tmp; @@ -727,39 +778,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); } @@ -767,9 +821,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); } @@ -793,8 +847,19 @@ static int statsd_metric_submit_unsafe (char const *name, /* {{{ */ else values[0].gauge = (gauge_t) c_avl_size (metric->set); } - else - values[0].derive = (derive_t) metric->value; + else { /* STATSD_COUNTER */ + /* + * Expand a single value to two metrics: + * + * - The absolute counter, as a gauge + * - A derived rate for this counter + */ + values[0].derive = (derive_t) metric->value; + plugin_dispatch_values(&vl); + + sstrncpy(vl.type, "gauge", sizeof (vl.type)); + values[0].gauge = (gauge_t) metric->value; + } return (plugin_dispatch_values (&vl)); } /* }}} int statsd_metric_submit_unsafe */ @@ -856,7 +921,7 @@ static int statsd_read (void) /* {{{ */ } sfree (name); - sfree (metric); + statsd_metric_free (metric); } pthread_mutex_unlock (&metrics_lock); @@ -871,8 +936,6 @@ static int statsd_shutdown (void) /* {{{ */ void *key; void *value; - pthread_mutex_lock (&metrics_lock); - if (network_thread_running) { network_thread_shutdown = 1; @@ -881,10 +944,12 @@ static int statsd_shutdown (void) /* {{{ */ } network_thread_running = 0; + pthread_mutex_lock (&metrics_lock); + while (c_avl_pick (metrics_tree, &key, &value) == 0) { sfree (key); - sfree (value); + statsd_metric_free (value); } c_avl_destroy (metrics_tree); metrics_tree = NULL;