=item B<LatencyRate> I<lower_latency> I<upper_latency>
Calculate and dispatch rate of latency values fall within requested interval.
-Interval specified as [I<lower_latency>,I<upper_latency>] (including boundaries).
-When I<upper_latency> value is equal to 0 then interval is [lower, infinity).
+Interval is specified as [I<lower_latency>, I<upper_latency>] (including
+boundaries). Rate cannot be reported for 0.000 latency, so I<lower_latency>
+should be 0.001 or greater. When I<upper_latency> value is equal to 0 then
+interval is [lower, infinity).
Rates for different intervals can be calculated by setting this option several
times.
#include "plugin.h"
#include "utils_latency.h"
-#include "utils_latency_config.h"
/*
* Each type may have 12 sub-types
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;
- value_t values[1];
match_value = (cu_match_value_t *) match_get_user_data (match);
if (match_value == NULL)
return (-1);
- vl.values = values;
+ vl.values = &(value_t) { .gauge = NAN };
vl.values_len = 1;
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, data->plugin, sizeof (vl.plugin));
if (data->latency_config.lower) {
ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"lower");
- values[0].gauge = (match_value->values_num != 0)
+ vl.values[0].gauge = (match_value->values_num != 0)
? CDTIME_T_TO_DOUBLE (latency_counter_get_min (match_value->latency))
: NAN;
plugin_dispatch_values (&vl);
if (data->latency_config.avg) {
ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"average");
- values[0].gauge = (match_value->values_num != 0)
+ vl.values[0].gauge = (match_value->values_num != 0)
? CDTIME_T_TO_DOUBLE (latency_counter_get_average (match_value->latency))
: NAN;
plugin_dispatch_values (&vl);
if (data->latency_config.upper) {
ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"upper");
- values[0].gauge = (match_value->values_num != 0)
+ vl.values[0].gauge = (match_value->values_num != 0)
? CDTIME_T_TO_DOUBLE (latency_counter_get_max (match_value->latency))
: NAN;
plugin_dispatch_values (&vl);
}
- size_t i;
/* Submit percentiles */
if (data->latency_config.percentile_type != NULL)
sstrncpy (vl.type, data->latency_config.percentile_type, sizeof (vl.type));
- for (i = 0; i < data->latency_config.percentile_num; i++)
+ for (size_t i = 0; i < data->latency_config.percentile_num; i++)
{
ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"percentile-%.0f", data->latency_config.percentile[i]);
- values[0].gauge = (match_value->values_num != 0)
+ vl.values[0].gauge = (match_value->values_num != 0)
? CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (match_value->latency,
data->latency_config.percentile[i]))
: NAN;
sstrncpy (vl.type, data->type, sizeof (vl.type));
if (data->latency_config.rates_type != NULL)
sstrncpy (vl.type, data->latency_config.rates_type, sizeof (vl.type));
- for (i = 0; i < data->latency_config.rates_num; i++)
+ for (size_t i = 0; i < data->latency_config.rates_num; i++)
{
ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"rate-%.3f-%.3f",
CDTIME_T_TO_DOUBLE(data->latency_config.rates[i * 2]),
CDTIME_T_TO_DOUBLE(data->latency_config.rates[i * 2 + 1]));
- values[0].gauge = (match_value->values_num != 0)
+ vl.values[0].gauge = (match_value->values_num != 0)
? latency_counter_get_rate (match_value->latency,
data->latency_config.rates[i * 2],
data->latency_config.rates[i * 2 + 1],
*/
#include "utils_match.h"
+#include "utils_latency_config.h"
struct cu_tail_match_s;
typedef struct cu_tail_match_s cu_tail_match_t;
}
else if (strcasecmp ("Latency", ci->values[0].value.string) == 0)
{
- cm->flags = UTILS_MATCH_DS_TYPE_GAUGE;
- cm->flags |= UTILS_MATCH_CF_GAUGE_LATENCY;
+ cm->flags = UTILS_MATCH_DS_TYPE_GAUGE | UTILS_MATCH_CF_GAUGE_LATENCY;
}
else if (strncasecmp ("Counter", ci->values[0].value.string, strlen ("Counter")) == 0)
{
if (lc->max < latency)
lc->max = latency;
- /* A latency of _exactly_ 1.0 ms should be stored in the buffer 0, so
+ /* A latency of _exactly_ 1.0 ms is stored in the buffer 0, so
* subtract one from the cdtime_t value so that exactly 1.0 ms get sorted
* accordingly. */
bin = (latency - 1) / lc->bin_width;
{
cdtime_t lower_bin;
cdtime_t upper_bin;
- double p;
double sum = 0;
- size_t i;
if ((lc == NULL) || (lc->num == 0))
return (0);
if (upper && (upper < lower))
return (0);
- /* A latency of _exactly_ 1.0 ms should be stored in the buffer 0 */
+ /* A latency of _exactly_ 1.0 ms is stored in the buffer 0 */
lower_bin = (lower - 1) / lc->bin_width;
if (upper)
}
sum = 0;
- for (i = lower_bin; i <= upper_bin; i++)
+ for (size_t i = lower_bin; i <= upper_bin; i++)
{
sum += lc->histogram[i];
}
- p = ((double)lower - (double)(lower_bin + 0) * (double)lc->bin_width - (double)DOUBLE_TO_CDTIME_T(0.001)) / (double)lc->bin_width;
- sum -= p * lc->histogram[lower_bin];
+ /* Approximate ratio of requests below "lower" */
+ cdtime_t lower_bin_boundary = lower_bin * lc->bin_width;
+
+ /* When bin width is 0.125 (for example), then bin 0 stores
+ * values for interval [0, 0.124) (excluding).
+ * With lower = 0.100, the ratio should be 0.099 / 0.125.
+ * I.e. ratio = 0.100 - 0.000 - 0.001
+ */
+ double ratio = (double)(lower - lower_bin_boundary - DOUBLE_TO_CDTIME_T(0.001))
+ / (double)lc->bin_width;
+ sum -= ratio * lc->histogram[lower_bin];
- if (upper && upper < (upper_bin + 1) * lc->bin_width)
+ /* Approximate ratio of requests above "upper" */
+ cdtime_t upper_bin_boundary = (upper_bin + 1) * lc->bin_width;
+ if (upper)
{
- // p = ((upper_bin + 1) * bin_width - upper ) / bin_width;
- p = ((double)(upper_bin + 1) * (double)lc->bin_width - (double)upper) / (double)lc->bin_width;
- sum -= p * lc->histogram[upper_bin];
+ assert (upper <= upper_bin_boundary);
+ double ratio = (double)(upper_bin_boundary - upper) / (double)lc->bin_width;
+ sum -= ratio * lc->histogram[upper_bin];
}
- return sum / (CDTIME_T_TO_DOUBLE (now - lc->start_time));
+ return sum / (CDTIME_T_TO_DOUBLE (now - lc->start_time));
} /* }}} double latency_counter_get_rate */
-
/* vim: set sw=2 sts=2 et fdm=marker : */
#include "common.h"
#include "utils_latency_config.h"
-int latency_config_add_percentile (const char *plugin, latency_config_t *cl,
- oconfig_item_t *ci)
+int latency_config_add_percentile(const char *plugin, latency_config_t *cl,
+ oconfig_item_t *ci)
{
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
{
- ERROR ("%s plugin: \"%s\" requires exactly one numeric argument.",
- plugin, ci->key);
+ ERROR("%s plugin: \"%s\" requires exactly one numeric argument.", plugin,
+ ci->key);
return (-1);
}
if ((percent <= 0.0) || (percent >= 100))
{
- ERROR ("%s plugin: The value for \"%s\" must be between 0 and 100, "
- "exclusively.", plugin, ci->key);
+ ERROR("%s plugin: The value for \"%s\" must be between 0 and 100, "
+ "exclusively.",
+ plugin, ci->key);
return (ERANGE);
}
- tmp = realloc (cl->percentile,
- sizeof (*cl->percentile) * (cl->percentile_num + 1));
+ tmp = realloc(cl->percentile,
+ sizeof(*cl->percentile) * (cl->percentile_num + 1));
if (tmp == NULL)
{
- ERROR ("%s plugin: realloc failed.", plugin);
+ ERROR("%s plugin: realloc failed.", plugin);
return (ENOMEM);
}
cl->percentile = tmp;
return (0);
} /* int latency_config_add_percentile */
-int latency_config_add_rate (const char *plugin, latency_config_t *cl,
- oconfig_item_t *ci)
+int latency_config_add_rate(const char *plugin, latency_config_t *cl,
+ oconfig_item_t *ci)
{
-
if ((ci->values_num != 2)
- ||(ci->values[0].type != OCONFIG_TYPE_NUMBER)
- ||(ci->values[1].type != OCONFIG_TYPE_NUMBER))
+ || (ci->values[0].type != OCONFIG_TYPE_NUMBER)
+ || (ci->values[1].type != OCONFIG_TYPE_NUMBER))
{
- ERROR ("%s plugin: \"%s\" requires exactly two numeric arguments.",
- plugin, ci->key);
+ ERROR("%s plugin: \"%s\" requires exactly two numeric arguments.", plugin,
+ ci->key);
return (-1);
}
if (ci->values[1].value.number &&
ci->values[1].value.number <= ci->values[0].value.number)
{
- ERROR ("%s plugin: MIN must be less than MAX in \"%s\".",
- plugin, ci->key);
+ ERROR("%s plugin: MIN must be less than MAX in \"%s\".", plugin, ci->key);
return (-1);
}
if (ci->values[0].value.number < 0.001)
{
- ERROR ("%s plugin: MIN must be greater or equal to 0.001 in \"%s\".",
- plugin, ci->key);
+ ERROR("%s plugin: MIN must be greater or equal to 0.001 in \"%s\".", plugin,
+ ci->key);
return (-1);
}
cdtime_t upper = DOUBLE_TO_CDTIME_T(ci->values[1].value.number);
cdtime_t *tmp;
- tmp = realloc (cl->rates,
- sizeof (*cl->rates) * (cl->rates_num + 1) * 2);
+ tmp = realloc(cl->rates, sizeof(*cl->rates) * (cl->rates_num + 1) * 2);
if (tmp == NULL)
{
- ERROR ("%s plugin: realloc failed.", plugin);
+ ERROR("%s plugin: realloc failed.", plugin);
return (ENOMEM);
}
cl->rates = tmp;
return (0);
} /* int latency_config_add_rate */
-
-int latency_config_copy (latency_config_t *dst, const latency_config_t src)
+int latency_config_copy(latency_config_t *dst, const latency_config_t src)
{
+ *dst = (latency_config_t){
+ .rates = NULL,
+ .rates_num = src.rates_num,
+ .rates_type = NULL,
+ .percentile = NULL,
+ .percentile_num = src.percentile_num,
+ .percentile_type = NULL,
+ };
+
/* Copy percentiles configuration */
dst->percentile_num = src.percentile_num;
- dst->percentile = malloc(sizeof (*dst->percentile) * (src.percentile_num));
+ dst->percentile = calloc(src.percentile_num, sizeof(*dst->percentile));
if (dst->percentile == NULL)
- goto nomem;
+ return (-1);
- memcpy (dst->percentile, src.percentile,
- (sizeof (*dst->percentile) * (src.percentile_num)));
+ memcpy(dst->percentile, src.percentile,
+ (sizeof(*dst->percentile) * (src.percentile_num)));
if (src.percentile_type != NULL)
{
dst->percentile_type = strdup(src.percentile_type);
if (dst->percentile_type == NULL)
- goto nomem;
+ {
+ latency_config_free(*dst);
+ return (-1);
+ }
}
/* Copy rates configuration */
dst->rates_num = src.rates_num;
- dst->rates = malloc(sizeof (*dst->rates) * (src.rates_num) * 2);
+ dst->rates = calloc(src.rates_num * 2, sizeof(*dst->rates));
if (dst->rates == NULL)
- goto nomem;
+ {
+ latency_config_free(*dst);
+ return (-1);
+ }
- memcpy (dst->rates, src.rates,
- (sizeof (*dst->rates) * (src.rates_num) * 2));
+ memcpy(dst->rates, src.rates, (sizeof(*dst->rates) * (src.rates_num) * 2));
if (src.rates_type != NULL)
{
dst->rates_type = strdup(src.rates_type);
if (dst->rates_type == NULL)
- goto nomem;
+ {
+ latency_config_free(*dst);
+ return (-1);
+ }
}
return (0);
-nomem:
- free (dst->rates);
- free (dst->rates_type);
- free (dst->percentile);
- free (dst->percentile_type);
- return (-1);
} /* int latency_config_copy */
-void latency_config_free (latency_config_t lc)
-{
- sfree (lc.rates);
- sfree (lc.rates_type);
- sfree (lc.percentile);
- sfree (lc.percentile_type);
+void latency_config_free(latency_config_t lc) {
+ sfree(lc.rates);
+ sfree(lc.rates_type);
+ sfree(lc.percentile);
+ sfree(lc.percentile_type);
} /* void latency_config_free */
struct latency_config_s
{
- double *percentile;
- size_t percentile_num;
- char *percentile_type;
+ double *percentile;
+ size_t percentile_num;
+ char *percentile_type;
cdtime_t *rates;
size_t rates_num;
char *rates_type;
- _Bool lower;
- _Bool upper;
+ _Bool lower;
+ _Bool upper;
//_Bool sum;
- _Bool avg;
+ _Bool avg;
//_Bool count;
};
typedef struct latency_config_s latency_config_t;
+int latency_config_add_percentile(const char *plugin, latency_config_t *cl,
+ oconfig_item_t *ci);
-int latency_config_add_percentile (const char *plugin, latency_config_t *cl,
- oconfig_item_t *ci);
+int latency_config_add_rate(const char *plugin, latency_config_t *cl,
+ oconfig_item_t *ci);
-int latency_config_add_rate (const char *plugin, latency_config_t *cl,
- oconfig_item_t *ci);
+int latency_config_copy(latency_config_t *dst, const latency_config_t src);
-int latency_config_copy (latency_config_t *dst, const latency_config_t src);
-
-void latency_config_free (latency_config_t lc);
+void latency_config_free(latency_config_t lc);
#endif /* UTILS_LATENCY_CONFIG_H */
for (i = 0; i < 125; i++) {
latency_counter_add (l, TIME_T_TO_CDTIME_T (((time_t) i) + 1));
}
- //Test expects bin width equal to 0.125s
+ //Test expects bin width will be equal to 0.125s
EXPECT_EQ_DOUBLE (1/125, latency_counter_get_rate (l,
DOUBLE_TO_CDTIME_T(10),