From 1d888f3f3a131f8eb2d9e0884665b6951ecee550 Mon Sep 17 00:00:00 2001 From: Pavel Rochnyack Date: Sat, 7 May 2016 23:26:15 +0600 Subject: [PATCH] + liblatency: Added utils_latency_config code + tail plugin: DSType Latency added --- src/Makefile.am | 4 +- src/collectd.conf.in | 20 ++++++ src/collectd.conf.pod | 31 ++++++++ src/daemon/Makefile.am | 4 +- src/daemon/utils_match.c | 26 +++++++ src/daemon/utils_match.h | 4 ++ src/daemon/utils_tail_match.c | 122 ++++++++++++++++++++++++++++++- src/daemon/utils_tail_match.h | 4 +- src/tail.c | 54 +++++++++++++- src/utils_latency_config.c | 163 ++++++++++++++++++++++++++++++++++++++++++ src/utils_latency_config.h | 61 ++++++++++++++++ 11 files changed, 486 insertions(+), 7 deletions(-) create mode 100644 src/utils_latency_config.c create mode 100644 src/utils_latency_config.h diff --git a/src/Makefile.am b/src/Makefile.am index fe2d2a8e..a01176d9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -52,7 +52,8 @@ test_format_json_LDADD = libformat_json.la daemon/libmetadata.la daemon/libplugi endif noinst_LTLIBRARIES += liblatency.la -liblatency_la_SOURCES = utils_latency.c utils_latency.h +liblatency_la_SOURCES = utils_latency.c utils_latency.h utils_latency_config.c utils_latency_config.h +liblatency_la_LIBADD = daemon/libcommon.la check_PROGRAMS += test_utils_latency TESTS += test_utils_latency test_utils_latency_SOURCES = utils_latency_test.c testing.h @@ -1115,6 +1116,7 @@ if BUILD_PLUGIN_TAIL pkglib_LTLIBRARIES += tail.la tail_la_SOURCES = tail.c tail_la_LDFLAGS = $(PLUGIN_LDFLAGS) +tail_la_LIBADD = liblatency.la endif if BUILD_PLUGIN_TAIL_CSV diff --git a/src/collectd.conf.in b/src/collectd.conf.in index 719010f4..037371bc 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -1272,6 +1272,26 @@ # Instance "local_user" # # +# +# #Use the following log format in nginx: +# #log_format response_time '[$host] "$upstream_response_time" ...' +# Instance "apache" +# +# Regex "^\\S+ \"([0-9.]+)\"" +# DSType "Latency" +# Type "response_time" +# #LatencyPercentileType "percentile" +# LatencyPercentile 5 +# LatencyPercentile 30 +# LatencyPercentile 50 +# LatencyPercentile 70 +# LatencyPercentile 95 +# LatencyRateType "requests" +# LatencyRate 0.001 0.100 +# LatencyRate 0.101 0.200 +# LatencyRate 0.201 0 +# +# # # diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index 4293abf3..0f99169b 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -7187,6 +7187,14 @@ Increase the internal counter by one. These B are the only ones that do not use the matched subexpression, but simply count the number of matched lines. Thus, you may use a regular expression without submatch in this case. +=item B + +Special type to handle latency values from logfiles. The matched value must be +latency in seconds, floating point numbers are supported. +Should be used with B or B options. + +The B option cannot be used together with B B. + =back As you'd expect the B types interpret the submatch as a floating point @@ -7205,6 +7213,29 @@ their configuration can be found in L. This optional setting sets the type instance to use. +=item B I + +Calculate and dispatch the configured percentile, i.e. compute the latency, so +that I of all matched latency values are smaller than or equal to the +computed latency. + +Different percentiles can be calculated by setting this option several times. + +=item B I +Sets the type used to dispatch B values. + +=item B I I + +Calculate and dispatch rate of latency values fall within requested interval. +Interval specified as [I,I] (including boundaries). +When I value is equal to 0 then interval is [lower, infinity). + +Rates for different intervals can be calculated by setting this option several +times. + +=item B I +Sets the type used to dispatch B values. + =back =head2 Plugin C diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am index cb62c645..ac8c7640 100644 --- a/src/daemon/Makefile.am +++ b/src/daemon/Makefile.am @@ -67,7 +67,9 @@ collectd_SOURCES = collectd.c collectd.h \ utils_tail.c utils_tail.h \ utils_time.c utils_time.h \ types_list.c types_list.h \ - utils_threshold.c utils_threshold.h + utils_threshold.c utils_threshold.h \ + ../utils_latency_config.h ../utils_latency_config.c \ + ../utils_latency.h ../utils_latency.c collectd_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL) diff --git a/src/daemon/utils_match.c b/src/daemon/utils_match.c index 2a39e4d0..98d93116 100644 --- a/src/daemon/utils_match.c +++ b/src/daemon/utils_match.c @@ -99,6 +99,13 @@ static int default_callback (const char __attribute__((unused)) *str, if (matches[1] == endptr) return (-1); + if (data->ds_type & UTILS_MATCH_CF_GAUGE_LATENCY) + { + latency_counter_add(data->latency, DOUBLE_TO_CDTIME_T(value)); + data->values_num++; + return (0); + } + if ((data->values_num == 0) || (data->ds_type & UTILS_MATCH_CF_GAUGE_LAST) || (data->ds_type & UTILS_MATCH_CF_GAUGE_PERSIST)) @@ -228,6 +235,10 @@ static int default_callback (const char __attribute__((unused)) *str, static void match_simple_free (void *data) { + cu_match_value_t *user_data = (cu_match_value_t *) data; + if (user_data->latency) + latency_counter_destroy(user_data->latency); + free (data); } /* void match_simple_free */ @@ -287,10 +298,25 @@ cu_match_t *match_create_simple (const char *regex, return (NULL); user_data->ds_type = match_ds_type; + if ((match_ds_type & UTILS_MATCH_DS_TYPE_GAUGE) + && (match_ds_type & UTILS_MATCH_CF_GAUGE_LATENCY)) + { + user_data->latency = latency_counter_create(); + if (user_data->latency == NULL) + { + ERROR ("match_create_simple(): latency_counter_create() failed."); + free (user_data); + return (NULL); + } + } + obj = match_create_callback (regex, excluderegex, default_callback, user_data, match_simple_free); if (obj == NULL) { + if (user_data->latency) + latency_counter_destroy(user_data->latency); + sfree (user_data); return (NULL); } diff --git a/src/daemon/utils_match.h b/src/daemon/utils_match.h index 31dc66d8..f8aba2c5 100644 --- a/src/daemon/utils_match.h +++ b/src/daemon/utils_match.h @@ -28,6 +28,8 @@ #define UTILS_MATCH_H 1 #include "plugin.h" +#include "utils_latency.h" +#include "utils_latency_config.h" /* * Each type may have 12 sub-types @@ -47,6 +49,7 @@ #define UTILS_MATCH_CF_GAUGE_INC 0x10 #define UTILS_MATCH_CF_GAUGE_ADD 0x20 #define UTILS_MATCH_CF_GAUGE_PERSIST 0x40 +#define UTILS_MATCH_CF_GAUGE_LATENCY 0x80 #define UTILS_MATCH_CF_COUNTER_SET 0x01 #define UTILS_MATCH_CF_COUNTER_ADD 0x02 @@ -71,6 +74,7 @@ struct cu_match_value_s int ds_type; value_t value; unsigned int values_num; + latency_counter_t *latency; }; typedef struct cu_match_value_s cu_match_value_t; diff --git a/src/daemon/utils_tail_match.c b/src/daemon/utils_tail_match.c index 99d5decb..0be8cfe2 100644 --- a/src/daemon/utils_tail_match.c +++ b/src/daemon/utils_tail_match.c @@ -36,6 +36,7 @@ #include "utils_match.h" #include "utils_tail.h" #include "utils_tail_match.h" +#include "utils_latency_config.h" struct cu_tail_match_simple_s { @@ -44,6 +45,7 @@ struct cu_tail_match_simple_s char type[DATA_MAX_NAME_LEN]; char type_instance[DATA_MAX_NAME_LEN]; cdtime_t interval; + latency_config_t latency_config; }; typedef struct cu_tail_match_simple_s cu_tail_match_simple_t; @@ -102,6 +104,95 @@ static int simple_submit_match (cu_match_t *match, void *user_data) return (0); } /* int simple_submit_match */ +static int simple_submit_latency (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; + 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_len = 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)); + sstrncpy (vl.type, data->type, sizeof (vl.type)); + vl.interval = data->interval; + vl.time = cdtime (); + + if (data->latency_config.lower) { + ssnprintf (vl.type_instance, sizeof (vl.type_instance), + "lower"); + 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) + ? 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) + ? 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++) + { + ssnprintf (vl.type_instance, sizeof (vl.type_instance), + "percentile-%.0f", data->latency_config.percentile[i]); + 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; + plugin_dispatch_values (&vl); + } + + /* Submit rates */ + 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++) + { + 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) + ? latency_counter_get_rate (match_value->latency, + data->latency_config.rates[i * 2], + data->latency_config.rates[i * 2 + 1], + vl.time) + : NAN; + plugin_dispatch_values (&vl); + } + latency_counter_reset (match_value->latency); + + match_value->value.gauge = NAN; + match_value->values_num = 0; + + return (0); +} /* int simple_submit_latency */ + static int tail_callback (void *data, char *buf, int __attribute__((unused)) buflen) { @@ -113,6 +204,13 @@ static int tail_callback (void *data, char *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 */ @@ -193,7 +291,9 @@ int tail_match_add_match (cu_tail_match_t *obj, cu_match_t *match, int tail_match_add_match_simple (cu_tail_match_t *obj, const char *regex, const char *excluderegex, int ds_type, const char *plugin, const char *plugin_instance, - const char *type, const char *type_instance, const cdtime_t interval) + const char *type, const char *type_instance, + const latency_config_t latency_cfg, + const cdtime_t interval) { cu_match_t *match; cu_tail_match_simple_t *user_data; @@ -222,13 +322,29 @@ int tail_match_add_match_simple (cu_tail_match_t *obj, user_data->interval = interval; - status = tail_match_add_match (obj, match, simple_submit_match, + if ((ds_type & UTILS_MATCH_DS_TYPE_GAUGE) + && (ds_type & UTILS_MATCH_CF_GAUGE_LATENCY)) + { + status = latency_config_copy(&user_data->latency_config, latency_cfg); + if (status != 0) + { + ERROR ("tail_match_add_match_simple: latency_config_copy() failed."); + status = -1; + goto out; + } + + status = tail_match_add_match (obj, match, simple_submit_latency, + user_data, tail_match_simple_free); + } else { + status = tail_match_add_match (obj, match, simple_submit_match, user_data, free); + } +out: if (status != 0) { + tail_match_simple_free(user_data); match_destroy (match); - sfree (user_data); } return (status); diff --git a/src/daemon/utils_tail_match.h b/src/daemon/utils_tail_match.h index 0404de2f..5601fcbd 100644 --- a/src/daemon/utils_tail_match.h +++ b/src/daemon/utils_tail_match.h @@ -103,6 +103,7 @@ int tail_match_add_match (cu_tail_match_t *obj, cu_match_t *match, * passed `plugin', `plugin_instance', `type', and `type_instance' are * directly used when submitting these values. * With excluderegex it is possible to exlude lines from the match. + * The `latency_cfg' specifies configuration for submitting latency. * * RETURN VALUE * Zero upon success, non-zero otherwise. @@ -110,7 +111,8 @@ int tail_match_add_match (cu_tail_match_t *obj, cu_match_t *match, int tail_match_add_match_simple (cu_tail_match_t *obj, const char *regex, const char *excluderegex, int ds_type, const char *plugin, const char *plugin_instance, - const char *type, const char *type_instance, const cdtime_t interval); + const char *type, const char *type_instance, const latency_config_t latency_cfg, + const cdtime_t interval); /* * NAME diff --git a/src/tail.c b/src/tail.c index 0ac8be7c..5326e7c1 100644 --- a/src/tail.c +++ b/src/tail.c @@ -29,6 +29,7 @@ #include "common.h" #include "plugin.h" #include "utils_tail_match.h" +#include "utils_latency_config.h" /* * @@ -54,6 +55,7 @@ struct ctail_config_match_s char *type; char *type_instance; cdtime_t interval; + latency_config_t latency; }; typedef struct ctail_config_match_s ctail_config_match_t; @@ -90,6 +92,11 @@ static int ctail_config_add_match_dstype (ctail_config_match_t *cm, else cm->flags = 0; } + else if (strcasecmp ("Latency", ci->values[0].value.string) == 0) + { + cm->flags = UTILS_MATCH_DS_TYPE_GAUGE; + cm->flags |= UTILS_MATCH_CF_GAUGE_LATENCY; + } else if (strncasecmp ("Counter", ci->values[0].value.string, strlen ("Counter")) == 0) { cm->flags = UTILS_MATCH_DS_TYPE_COUNTER; @@ -163,6 +170,28 @@ static int ctail_config_add_match (cu_tail_match_t *tm, status = cf_util_get_string (option, &cm.type); else if (strcasecmp ("Instance", option->key) == 0) status = cf_util_get_string (option, &cm.type_instance); + else if (strncasecmp ("Latency", option->key, strlen ("Latency")) == 0) + { + if (strcasecmp ("LatencyPercentile", option->key) == 0) + status = latency_config_add_percentile ("tail", &cm.latency, option); + else if (strcasecmp ("LatencyPercentileType", option->key) == 0) + status = cf_util_get_string (option, &cm.latency.percentile_type); + else if (strcasecmp ("LatencyRate", option->key) == 0) + status = latency_config_add_rate ("tail", &cm.latency, option); + else if (strcasecmp ("LatencyRateType", option->key) == 0) + status = cf_util_get_string (option, &cm.latency.rates_type); + else if (strcasecmp ("LatencyLower", option->key) == 0) + status = cf_util_get_boolean (option, &cm.latency.lower); + else if (strcasecmp ("LatencyUpper", option->key) == 0) + status = cf_util_get_boolean (option, &cm.latency.upper); + else if (strcasecmp ("LatencyAvg", option->key) == 0) + status = cf_util_get_boolean (option, &cm.latency.avg); + else + { + WARNING ("tail plugin: Option `%s' not allowed here.", option->key); + status = -1; + } + } else { WARNING ("tail plugin: Option `%s' not allowed here.", option->key); @@ -196,13 +225,35 @@ static int ctail_config_add_match (cu_tail_match_t *tm, break; } + if ((cm.flags & UTILS_MATCH_DS_TYPE_GAUGE) + && (cm.flags & UTILS_MATCH_CF_GAUGE_LATENCY)) + { + + if (cm.type_instance != NULL) + { + WARNING ("tail plugin: `DSType Latency' and `Instance %s' in `Match' " + "block could not be used together.", cm.type_instance); + status = -1; + break; + } + + if (cm.latency.percentile_num == 0 && cm.latency.rates_num == 0) + { + WARNING ("tail plugin: `Match' with `DSType Latency' has no " + "`LatencyPercentile' or `LatencyRate' options."); + status = -1; + break; + } + } + break; } /* while (status == 0) */ if (status == 0) { status = tail_match_add_match_simple (tm, cm.regex, cm.excluderegex, - cm.flags, "tail", plugin_instance, cm.type, cm.type_instance, interval); + cm.flags, "tail", plugin_instance, cm.type, cm.type_instance, + cm.latency, interval); if (status != 0) { @@ -214,6 +265,7 @@ static int ctail_config_add_match (cu_tail_match_t *tm, sfree (cm.excluderegex); sfree (cm.type); sfree (cm.type_instance); + latency_config_free(cm.latency); return (status); } /* int ctail_config_add_match */ diff --git a/src/utils_latency_config.c b/src/utils_latency_config.c new file mode 100644 index 00000000..7504aafb --- /dev/null +++ b/src/utils_latency_config.c @@ -0,0 +1,163 @@ +/** + * collectd - src/utils_latency_config.c + * Copyright (C) 2013-2016 Florian octo Forster + * + * 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", 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 + * Pavel Rochnyack + */ + +#include "collectd.h" +#include "common.h" +#include "utils_latency_config.h" + +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); + return (-1); + } + + double percent = ci->values[0].value.number; + double *tmp; + + if ((percent <= 0.0) || (percent >= 100)) + { + 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)); + if (tmp == NULL) + { + ERROR ("%s plugin: realloc failed.", plugin); + return (ENOMEM); + } + cl->percentile = tmp; + cl->percentile[cl->percentile_num] = percent; + cl->percentile_num++; + + return (0); +} /* int latency_config_add_percentile */ + +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)) + { + 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); + 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); + return (-1); + } + + cdtime_t lower = DOUBLE_TO_CDTIME_T(ci->values[0].value.number); + 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); + if (tmp == NULL) + { + ERROR ("%s plugin: realloc failed.", plugin); + return (ENOMEM); + } + cl->rates = tmp; + cl->rates[cl->rates_num * 2] = lower; + cl->rates[cl->rates_num * 2 + 1] = upper; + cl->rates_num++; + + return (0); +} /* int latency_config_add_rate */ + + +int latency_config_copy (latency_config_t *dst, const latency_config_t src) +{ + /* Copy percentiles configuration */ + dst->percentile_num = src.percentile_num; + dst->percentile = malloc(sizeof (*dst->percentile) * (src.percentile_num)); + if (dst->percentile == NULL) + goto nomem; + + 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; + } + + /* Copy rates configuration */ + dst->rates_num = src.rates_num; + dst->rates = malloc(sizeof (*dst->rates) * (src.rates_num) * 2); + if (dst->rates == NULL) + goto nomem; + + 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; + } + + 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 */ diff --git a/src/utils_latency_config.h b/src/utils_latency_config.h new file mode 100644 index 00000000..283ce1c4 --- /dev/null +++ b/src/utils_latency_config.h @@ -0,0 +1,61 @@ +/** + * collectd - src/utils_latency_config.c + * Copyright (C) 2013-2016 Florian octo Forster + * + * 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", 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 + * Pavel Rochnyack + */ + +#ifndef UTILS_LATENCY_CONFIG_H +#define UTILS_LATENCY_CONFIG_H 1 + +#include "collectd.h" +#include "utils_time.h" + +struct latency_config_s +{ + double *percentile; + size_t percentile_num; + char *percentile_type; + cdtime_t *rates; + size_t rates_num; + char *rates_type; + _Bool lower; + _Bool upper; + //_Bool sum; + _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_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); + +void latency_config_free (latency_config_t lc); + +#endif /* UTILS_LATENCY_CONFIG_H */ -- 2.11.0