latency_counter_t *latency_counter_create (void) /* {{{ */ { latency_counter_t *lc; lc = calloc (1, sizeof (*lc)); if (lc == NULL) return (NULL); latency_counter_reset (lc); lc->bin_width = HISTOGRAM_DEFAULT_BIN_WIDTH; return (lc); } /* }}} latency_counter_t *latency_counter_create */
/* Must hold metrics_lock when calling this function. */ static int statsd_metric_submit_unsafe (statsd_config_t *conf, char const *name, /* {{{ */ statsd_metric_t const *metric) { value_t values[1]; value_list_t vl = VALUE_LIST_INIT; char *global_prefix = NULL; char *type_prefix = NULL; char *global_postfix = NULL; char full_name[DATA_MAX_NAME_LEN] = {0}; DEBUG("statsd plugin: submit metric"); vl.values = values; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "statsd", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, conf->node_name, sizeof (vl.plugin_instance)); global_prefix = (NULL == conf->global_prefix) ? "" : conf->global_prefix; global_postfix = (NULL == conf->global_postfix) ? "" : conf->global_postfix; switch (metric->type) { case STATSD_GAUGE: sstrncpy (vl.type, "gauge", sizeof (vl.type)); type_prefix = (NULL == conf->gauge_prefix) ? "" : conf->gauge_prefix; break; case STATSD_TIMER: sstrncpy (vl.type, "latency", sizeof (vl.type)); type_prefix = (NULL == conf->timer_prefix) ? "" : conf->timer_prefix; break; case STATSD_SET: sstrncpy (vl.type, "objects", sizeof (vl.type)); type_prefix = (NULL == conf->set_prefix) ? "" : conf->set_prefix; break; case STATSD_COUNTER: sstrncpy (vl.type, "derive", sizeof (vl.type)); type_prefix = (NULL == conf->counter_prefix) ? "" : conf->counter_prefix; break; default: ERROR("statsd plugin: unknow metrics type %d", metric->type); } ssnprintf(full_name, sizeof(full_name), "%s%s%s%s", global_prefix, type_prefix, name, global_postfix); DEBUG("statsd plugin: metric name %s", full_name); sstrncpy (vl.type_instance, full_name, sizeof (vl.type_instance)); if (metric->type == STATSD_GAUGE) values[0].gauge = (gauge_t) metric->value; else if (metric->type == STATSD_TIMER) { size_t i; _Bool have_events = (metric->updates_num > 0); /* Make sure all timer metrics share the *same* timestamp. */ vl.time = cdtime (); if (!conf->leave_metrics_name_asis) ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-average", full_name); 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", full_name); 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", full_name); 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", full_name); values[0].gauge = have_events ? CDTIME_T_TO_DOUBLE (latency_counter_get_sum (metric->latency)) : NAN; plugin_dispatch_values (&vl); } for (i = 0; i < conf->timer_percentile_num; i++) { ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-percentile-%.0f", full_name, 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); } /* Keep this at the end, since vl.type is set to "gauge" here. The * vl.type's above are implicitly set to "latency". */ if (conf->timer_count) { sstrncpy (vl.type, "gauge", sizeof (vl.type)); ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-count", full_name); values[0].gauge = latency_counter_get_num (metric->latency); plugin_dispatch_values (&vl); } latency_counter_reset (metric->latency); return (0); } else if (metric->type == STATSD_SET) { if (metric->set == NULL) values[0].gauge = 0.0; else values[0].gauge = (gauge_t) c_avl_size (metric->set); } 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 */
/* Must hold metrics_lock when calling this function. */ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metric) /* {{{ */ { value_t values[1]; value_list_t vl = VALUE_LIST_INIT; vl.values = values; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "statsd", sizeof (vl.plugin)); if (metric->type == STATSD_GAUGE) sstrncpy (vl.type, "gauge", sizeof (vl.type)); else if (metric->type == STATSD_TIMER) sstrncpy (vl.type, "latency", sizeof (vl.type)); else if (metric->type == STATSD_SET) sstrncpy (vl.type, "objects", sizeof (vl.type)); else /* if (metric->type == STATSD_COUNTER) */ sstrncpy (vl.type, "derive", sizeof (vl.type)); sstrncpy (vl.type_instance, name, sizeof (vl.type_instance)); if (metric->type == STATSD_GAUGE) values[0].gauge = (gauge_t) metric->value; else if (metric->type == STATSD_TIMER) { size_t i; _Bool have_events = (metric->updates_num > 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 = 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 = 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 = 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 = have_events ? CDTIME_T_TO_DOUBLE (latency_counter_get_sum (metric->latency)) : NAN; plugin_dispatch_values (&vl); } for (i = 0; i < conf_timer_percentile_num; i++) { ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-percentile-%.0f", name, 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); } /* Keep this at the end, since vl.type is set to "gauge" here. The * vl.type's above are implicitly set to "latency". */ if (conf_timer_count) { sstrncpy (vl.type, "gauge", sizeof (vl.type)); ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-count", name); values[0].gauge = latency_counter_get_num (metric->latency); plugin_dispatch_values (&vl); } latency_counter_reset (metric->latency); return (0); } else if (metric->type == STATSD_SET) { if (metric->set == NULL) values[0].gauge = 0.0; else values[0].gauge = (gauge_t) c_avl_size (metric->set); } else { /* STATSD_COUNTER */ gauge_t delta = nearbyint (metric->value); /* Etsy's statsd writes counters as two metrics: a rate and the change since * the last write. Since collectd does not reset its DERIVE metrics to zero, * this makes little sense, but we're dispatching a "count" metric here * anyway - if requested by the user - for compatibility reasons. */ if (conf_counter_sum) { sstrncpy (vl.type, "count", sizeof (vl.type)); values[0].gauge = delta; plugin_dispatch_values (&vl); /* restore vl.type */ sstrncpy (vl.type, "derive", sizeof (vl.type)); } /* Rather than resetting value to zero, subtract delta so we correctly keep * track of residuals. */ metric->value -= delta; metric->counter += (derive_t) delta; values[0].derive = metric->counter; } return (plugin_dispatch_values (&vl)); } /* }}} int statsd_metric_submit_unsafe */
/* Must hold metrics_lock when calling this function. */ static int statsd_metric_submit_unsafe (char const *name, /* {{{ */ statsd_metric_t const *metric) { value_t values[1]; value_list_t vl = VALUE_LIST_INIT; vl.values = values; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "statsd", sizeof (vl.plugin)); if (metric->type == STATSD_GAUGE) sstrncpy (vl.type, "gauge", sizeof (vl.type)); else if (metric->type == STATSD_TIMER) sstrncpy (vl.type, "latency", sizeof (vl.type)); else if (metric->type == STATSD_SET) sstrncpy (vl.type, "objects", sizeof (vl.type)); else /* if (metric->type == STATSD_COUNTER) */ sstrncpy (vl.type, "derive", sizeof (vl.type)); sstrncpy (vl.type_instance, name, sizeof (vl.type_instance)); if (metric->type == STATSD_GAUGE) values[0].gauge = (gauge_t) metric->value; else if (metric->type == STATSD_TIMER) { size_t i; _Bool have_events = (metric->updates_num > 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 = 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 = 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 = 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 = have_events ? CDTIME_T_TO_DOUBLE (latency_counter_get_sum (metric->latency)) : NAN; plugin_dispatch_values (&vl); } for (i = 0; i < conf_timer_percentile_num; i++) { ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-percentile-%.0f", name, 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); } /* Keep this at the end, since vl.type is set to "gauge" here. The * vl.type's above are implicitly set to "latency". */ if (conf_timer_count) { sstrncpy (vl.type, "gauge", sizeof (vl.type)); ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-count", name); values[0].gauge = latency_counter_get_num (metric->latency); plugin_dispatch_values (&vl); } latency_counter_reset (metric->latency); return (0); } else if (metric->type == STATSD_SET) { if (metric->set == NULL) values[0].gauge = 0.0; else values[0].gauge = (gauge_t) c_avl_size (metric->set); } else values[0].derive = (derive_t) metric->value; return (plugin_dispatch_values (&vl)); } /* }}} int statsd_metric_submit_unsafe */
static int latency_submit_match(cu_match_t *match, void *user_data) { cu_tail_match_simple_t *data = (cu_tail_match_simple_t *)user_data; cu_match_value_t *match_value; value_list_t vl = VALUE_LIST_INIT; match_value = (cu_match_value_t *)match_get_user_data(match); if (match_value == NULL) return (-1); sstrncpy(vl.host, hostname_g, sizeof(vl.host)); sstrncpy(vl.plugin, data->plugin, sizeof(vl.plugin)); sstrncpy(vl.plugin_instance, data->plugin_instance, sizeof(vl.plugin_instance)); vl.interval = data->interval; vl.time = cdtime(); /* Submit percentiles */ sstrncpy(vl.type, data->type, sizeof(vl.type)); for (size_t i = 0; i < data->latency_config.percentile_num; i++) { if (strlen(data->type_instance) != 0) ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%.0f", data->type_instance, data->latency_config.percentile[i]); else ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%.0f", data->latency_config.percentile[i]); vl.values = &(value_t){ .gauge = (match_value->values_num != 0) ? CDTIME_T_TO_DOUBLE(latency_counter_get_percentile( match_value->latency, data->latency_config.percentile[i])) : NAN, }; vl.values_len = 1; plugin_dispatch_values(&vl); } /* Submit buckets */ sstrncpy(vl.type, "bucket", sizeof(vl.type)); for (size_t i = 0; i < data->latency_config.buckets_num; i++) { latency_bucket_t bucket = data->latency_config.buckets[i]; double lower_bound = CDTIME_T_TO_DOUBLE(bucket.lower_bound); double upper_bound = bucket.upper_bound ? CDTIME_T_TO_DOUBLE(bucket.upper_bound) : INFINITY; if (strlen(data->type_instance) != 0) ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%s-%g_%g", data->type, data->type_instance, lower_bound, upper_bound); else ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%g_%g", data->type, lower_bound, upper_bound); vl.values = &(value_t){ .gauge = latency_counter_get_rate(match_value->latency, bucket.lower_bound, bucket.upper_bound, vl.time), }; vl.values_len = 1; plugin_dispatch_values(&vl); } match_value->value.gauge = NAN; match_value->values_num = 0; latency_counter_reset(match_value->latency); return (0); } /* int latency_submit_match */ static int tail_callback(void *data, char *buf, int __attribute__((unused)) buflen) { cu_tail_match_t *obj = (cu_tail_match_t *)data; for (size_t i = 0; i < obj->matches_num; i++) match_apply(obj->matches[i].match, buf); return (0); } /* int tail_callback */ static void tail_match_simple_free(void *data) { cu_tail_match_simple_t *user_data = (cu_tail_match_simple_t *)data; latency_config_free(user_data->latency_config); sfree(user_data); } /* void tail_match_simple_free */ /* * Public functions */ cu_tail_match_t *tail_match_create(const char *filename) { cu_tail_match_t *obj; obj = calloc(1, sizeof(*obj)); if (obj == NULL) return (NULL); obj->tail = cu_tail_create(filename); if (obj->tail == NULL) { sfree(obj); return (NULL); } return (obj); } /* cu_tail_match_t *tail_match_create */