summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 42dc3f7)
raw | patch | inline | side by side (parent: 42dc3f7)
author | Pavel Rochnyack <pavel2000@ngs.ru> | |
Sat, 7 May 2016 17:26:15 +0000 (23:26 +0600) | ||
committer | Florian Forster <octo@collectd.org> | |
Sun, 27 Nov 2016 06:55:28 +0000 (07:55 +0100) |
+ tail plugin: DSType Latency added
src/Makefile.am | patch | blob | history | |
src/collectd.conf.in | patch | blob | history | |
src/collectd.conf.pod | patch | blob | history | |
src/daemon/Makefile.am | patch | blob | history | |
src/daemon/utils_match.c | patch | blob | history | |
src/daemon/utils_match.h | patch | blob | history | |
src/daemon/utils_tail_match.c | patch | blob | history | |
src/daemon/utils_tail_match.h | patch | blob | history | |
src/tail.c | patch | blob | history | |
src/utils_latency_config.c | [new file with mode: 0644] | patch | blob |
src/utils_latency_config.h | [new file with mode: 0644] | patch | blob |
diff --git a/src/Makefile.am b/src/Makefile.am
index fe2d2a8ecbf4347c4a0efa9d3d061dff22ea112e..a01176d90e09971ebd65a1f4ddbe2d4b8498ece5 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
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
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 719010f4b71d4d7f825d726dc3995a5a898bdfa2..037371bca80d21084cb6e78f369a4e615f1fc2fb 100644 (file)
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
# Instance "local_user"
# </Match>
# </File>
+# <File "/var/log/nginx/apache-time.log">
+# #Use the following log format in nginx:
+# #log_format response_time '[$host] "$upstream_response_time" ...'
+# Instance "apache"
+# <Match>
+# 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
+# </Match>
+# </File>
#</Plugin>
#<Plugin tail_csv>
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 4293abf34b76c5c53bb051e19979d67eefbb9c84..0f99169b4055751db48eb12e3e549af2697b7d7f 100644 (file)
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
@@ -7187,6 +7187,14 @@ Increase the internal counter by one. These B<DSType> 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<Latency>
+
+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<LatencyPercentile> or B<LatencyRate> options.
+
+The B<Instance> option cannot be used together with B<DSType> B<Latency>.
+
=back
As you'd expect the B<Gauge*> types interpret the submatch as a floating point
This optional setting sets the type instance to use.
+=item B<LatencyPercentile> I<Percent>
+
+Calculate and dispatch the configured percentile, i.e. compute the latency, so
+that I<Percent> 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<LatencyPercentileType> I<Type>
+Sets the type used to dispatch B<LatencyPercentile> values.
+
+=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).
+
+Rates for different intervals can be calculated by setting this option several
+times.
+
+=item B<LatencyRateType> I<Type>
+Sets the type used to dispatch B<LatencyRate> values.
+
=back
=head2 Plugin C<tail_csv>
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index cb62c645cd5216e2143c26323fc57e14f50ddb8c..ac8c7640534b2d7dc7a8388f966e9ed47dd57cc5 100644 (file)
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
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)
index 2a39e4d0552b439623de8b18bf59c2aab9b3eda4..98d9311641c394a5bef6a66bfa6b28b33e3cd78a 100644 (file)
--- a/src/daemon/utils_match.c
+++ b/src/daemon/utils_match.c
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))
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 */
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);
}
index 31dc66d804b84cfc18685e37076d47aa26b503ca..f8aba2c54a95ab9bc87bcff89662bb965baf67d8 100644 (file)
--- a/src/daemon/utils_match.h
+++ b/src/daemon/utils_match.h
#define UTILS_MATCH_H 1
#include "plugin.h"
+#include "utils_latency.h"
+#include "utils_latency_config.h"
/*
* Each type may have 12 sub-types
#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
int ds_type;
value_t value;
unsigned int values_num;
+ latency_counter_t *latency;
};
typedef struct cu_match_value_s cu_match_value_t;
index 99d5decbec4dd069150c0cd8a576fc78f6e6f6ad..0be8cfe28e26cda47cc03d173d0d1b734b1deb9e 100644 (file)
#include "utils_match.h"
#include "utils_tail.h"
#include "utils_tail_match.h"
+#include "utils_latency_config.h"
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;
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)
{
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
*/
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;
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);
index 0404de2f2b6cfb14fbef5b34357366843d99ebff..5601fcbd6e6c5c7f4887e59af11132dc4344087b 100644 (file)
* 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.
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 0ac8be7c87049be84415d33e71e0af8bed1ec482..5326e7c18c7910e197fd97d0a6ad43c8ca879a64 100644 (file)
--- a/src/tail.c
+++ b/src/tail.c
#include "common.h"
#include "plugin.h"
#include "utils_tail_match.h"
+#include "utils_latency_config.h"
/*
* <Plugin tail>
char *type;
char *type_instance;
cdtime_t interval;
+ latency_config_t latency;
};
typedef struct ctail_config_match_s ctail_config_match_t;
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;
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);
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)
{
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
--- /dev/null
@@ -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 <octo at collectd.org>
+ * Pavel Rochnyack <pavel2000 at ngs.ru>
+ */
+
+#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
--- /dev/null
@@ -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 <octo at collectd.org>
+ * Pavel Rochnyack <pavel2000 at ngs.ru>
+ */
+
+#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 */