[collectd] [RFC 1/2] Add DDERIVE type
David Gibson
david at gibson.dropbear.id.au
Sat Aug 13 13:10:23 CEST 2016
This adds a new DDERIVE ds-type to collectd. This is modelled on the
DDERIVE type in recent rrdtool versions - the semantics are the same as
DERIVE, but it has floating point (double) values, instead of integers.
Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
---
contrib/collectd_network.py | 4 ++++
src/collectd-perl.pod | 4 +++-
src/csv.c | 9 ++++++++-
src/curl.c | 11 +++++++++++
src/curl_xml.c | 5 +++++
src/daemon/collectd.h | 4 ++++
src/daemon/common.c | 25 +++++++++++++++++++++++++
src/daemon/common_test.c | 3 +++
src/daemon/plugin.c | 3 +++
src/daemon/plugin.h | 4 ++++
src/daemon/types_list.c | 2 ++
src/daemon/utils_cache.c | 15 +++++++++++++++
src/daemon/utils_match.c | 24 ++++++++++++++++++++++++
src/daemon/utils_match.h | 12 ++++++++----
src/java.c | 10 ++++++++--
src/perl.c | 8 +++++++-
src/python.c | 6 +++++-
src/pyvalues.c | 14 ++++++++++++++
src/redis.c | 3 +++
src/rrdcached.c | 9 +++++++--
src/tail.c | 10 ++++++++++
src/target_scale.c | 13 +++++++++++++
src/utils_format_graphite.c | 2 ++
src/utils_format_json.c | 7 +++++++
src/utils_format_json.h | 4 ++++
src/utils_format_kairosdb.c | 20 ++++++++++++++++++++
src/utils_format_kairosdb.h | 4 ++++
src/utils_rrdcreate.c | 2 ++
src/write_mongodb.c | 2 ++
src/write_riemann.c | 7 +++++++
src/write_sensu.c | 10 +++++++++-
src/write_tsdb.c | 2 ++
32 files changed, 245 insertions(+), 13 deletions(-)
diff --git a/contrib/collectd_network.py b/contrib/collectd_network.py
index 809f19d..fa7f5e9 100644
--- a/contrib/collectd_network.py
+++ b/contrib/collectd_network.py
@@ -63,6 +63,7 @@ DS_TYPE_COUNTER = 0
DS_TYPE_GAUGE = 1
DS_TYPE_DERIVE = 2
DS_TYPE_ABSOLUTE = 3
+DS_TYPE_DDERIVE = 4
header = struct.Struct("!2H")
number = struct.Struct("!Q")
@@ -94,6 +95,9 @@ def decode_network_values(ptype, plen, buf):
elif dstype == DS_TYPE_ABSOLUTE:
result.append((dstype, number.unpack_from(buf, off)[0]))
off += valskip
+ elif dstype == DS_TYPE_DDERIVE:
+ result.append((dstype, number.unpack_from(buf, off)[0]))
+ off += valskip
else:
raise ValueError("DS type %i unsupported" % dstype)
diff --git a/src/collectd-perl.pod b/src/collectd-perl.pod
index 0102e92..491f28b 100644
--- a/src/collectd-perl.pod
+++ b/src/collectd-perl.pod
@@ -186,7 +186,7 @@ structure. The general layout looks like this:
[{
name => 'data_source_name',
- type => DS_TYPE_COUNTER || DS_TYPE_GAUGE || DS_TYPE_DERIVE || DS_TYPE_ABSOLUTE,
+ type => DS_TYPE_COUNTER || DS_TYPE_GAUGE || DS_TYPE_DERIVE || DS_TYPE_ABSOLUTE || DS_TYPE_DDERIVE,
min => value || undef,
max => value || undef
}, ...]
@@ -567,6 +567,8 @@ available (B<:all> will export all of them):
=item B<DS_TYPE_ABSOLUTE>
+=item B<DS_TYPE_DDERIVE>
+
=back
=item B<:log>
diff --git a/src/csv.c b/src/csv.c
index e008ecf..8c26d47 100644
--- a/src/csv.c
+++ b/src/csv.c
@@ -63,7 +63,8 @@ static int value_list_to_string (char *buffer, int buffer_len,
if ((ds->ds[i].type != DS_TYPE_COUNTER)
&& (ds->ds[i].type != DS_TYPE_GAUGE)
&& (ds->ds[i].type != DS_TYPE_DERIVE)
- && (ds->ds[i].type != DS_TYPE_ABSOLUTE))
+ && (ds->ds[i].type != DS_TYPE_ABSOLUTE)
+ && (ds->ds[i].type != DS_TYPE_DDERIVE))
{
sfree (rates);
return (-1);
@@ -109,6 +110,12 @@ static int value_list_to_string (char *buffer, int buffer_len,
",%"PRIu64,
vl->values[i].absolute);
}
+ else if (ds->ds[i].type == DS_TYPE_DDERIVE)
+ {
+ status = ssnprintf (buffer + offset,
+ buffer_len - offset,
+ ",%lf", vl->values[i].dderive);
+ }
if ((status < 1) || (status >= (buffer_len - offset)))
{
diff --git a/src/curl.c b/src/curl.c
index 8d7baa5..70ce32f 100644
--- a/src/curl.c
+++ b/src/curl.c
@@ -248,6 +248,17 @@ else if (strncasecmp ("Absolute", ci->values[0].value.string,
else
dstype = 0;
}
+else if (strncasecmp ("DDerive", ci->values[0].value.string,
+ strlen ("DDerive")) == 0)
+ {
+ dstype = UTILS_MATCH_DS_TYPE_DDERIVE;
+ if (strcasecmp ("DDeriveSet", ci->values[0].value.string) == 0)
+ dstype |= UTILS_MATCH_CF_DDERIVE_SET;
+ else if (strcasecmp ("DDeriveAdd", ci->values[0].value.string) == 0)
+ dstype |= UTILS_MATCH_CF_DDERIVE_ADD;
+ else
+ dstype = 0;
+ }
else
{
diff --git a/src/curl_xml.c b/src/curl_xml.c
index f3aa2d9..1894c93 100644
--- a/src/curl_xml.c
+++ b/src/curl_xml.c
@@ -351,6 +351,11 @@ static int cx_handle_single_value_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */
case DS_TYPE_GAUGE:
vl->values[index].gauge = (gauge_t) strtod (node_value,
/* endptr = */ NULL);
+ break;
+ case DS_TYPE_DDERIVE:
+ vl->values[index].dderive = (dderive_t) strtod (node_value,
+ /* endptr = */ NULL);
+ break;
}
/* free up object */
diff --git a/src/daemon/collectd.h b/src/daemon/collectd.h
index 3cb0c1b..df1a623 100644
--- a/src/daemon/collectd.h
+++ b/src/daemon/collectd.h
@@ -305,6 +305,10 @@ typedef int _Bool;
# define GAUGE_FORMAT "%.15g"
#endif
+#ifndef DDERIVE_FORMAT
+# define DDERIVE_FORMAT "%.15g"
+#endif
+
/* Type for time as used by "utils_time.h" */
typedef uint64_t cdtime_t;
diff --git a/src/daemon/common.c b/src/daemon/common.c
index 05b1199..220201b 100644
--- a/src/daemon/common.c
+++ b/src/daemon/common.c
@@ -984,6 +984,8 @@ int format_values (char *ret, size_t ret_len, /* {{{ */
BUFFER_ADD (":%"PRIi64, vl->values[i].derive);
else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
BUFFER_ADD (":%"PRIu64, vl->values[i].absolute);
+ else if (ds->ds[i].type == DS_TYPE_DDERIVE)
+ BUFFER_ADD (":"DDERIVE_FORMAT, vl->values[i].dderive);
else
{
ERROR ("format_values: Unknown data source type: %i",
@@ -1117,6 +1119,10 @@ int parse_value (const char *value_orig, value_t *ret_value, int ds_type)
ret_value->absolute = (absolute_t) strtoull (value, &endptr, 0);
break;
+ case DS_TYPE_DDERIVE:
+ ret_value->dderive = (dderive_t) strtod (value, &endptr);
+ break;
+
default:
sfree (value);
ERROR ("parse_value: Invalid data source type: %i.", ds_type);
@@ -1188,6 +1194,8 @@ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
vl->values[i].gauge = NAN;
+ else if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_DDERIVE))
+ vl->values[i].dderive = NAN;
else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
return -1;
@@ -1423,6 +1431,11 @@ int rate_to_value (value_t *ret_value, gauge_t rate, /* {{{ */
state->last_value.absolute = (absolute_t) rate;
state->residual = rate - ((gauge_t) state->last_value.absolute);
}
+ else if (ds_type == DS_TYPE_DDERIVE)
+ {
+ state->last_value.dderive = (dderive_t) rate;
+ state->residual = 0.0;
+ }
else
{
assert (23 == 42);
@@ -1453,6 +1466,13 @@ int rate_to_value (value_t *ret_value, gauge_t rate, /* {{{ */
state->last_value.absolute = delta_absolute;
state->residual = delta_gauge - ((gauge_t) delta_absolute);
}
+ else if (ds_type == DS_TYPE_DDERIVE)
+ {
+ dderive_t delta_dderive = (dderive_t) delta_gauge;
+
+ state->last_value.dderive += delta_dderive;
+ state->residual = 0.0;
+ }
else
{
assert (23 == 42);
@@ -1505,6 +1525,11 @@ int value_to_rate (gauge_t *ret_rate, /* {{{ */
*ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
break;
}
+ case DS_TYPE_DDERIVE: {
+ dderive_t diff = value.dderive - state->last_value.dderive;
+ *ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
+ break;
+ }
default:
return EINVAL;
}
diff --git a/src/daemon/common_test.c b/src/daemon/common_test.c
index 202ddf6..f520f5e 100644
--- a/src/daemon/common_test.c
+++ b/src/daemon/common_test.c
@@ -357,6 +357,9 @@ DEF_TEST(value_to_rate)
{20, 30, DS_TYPE_COUNTER, {.counter = 4294967238ULL}, {.counter = 42}, 10.0},
/* 64bit wrap-around. */
{30, 40, DS_TYPE_COUNTER, {.counter = 18446744073709551558ULL}, {.counter = 42}, 10.0},
+ { 0, 10, DS_TYPE_DDERIVE, {.dderive = 0.0}, {.dderive = 100.0}, NAN},
+ {10, 20, DS_TYPE_DDERIVE, {.dderive = 100.0}, {.dderive = 200.0}, 10.0},
+ {20, 30, DS_TYPE_DDERIVE, {.dderive = 200.0}, {.dderive = 195.0}, -0.5},
};
for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
diff --git a/src/daemon/plugin.c b/src/daemon/plugin.c
index 1bee8cd..5b35fe4 100644
--- a/src/daemon/plugin.c
+++ b/src/daemon/plugin.c
@@ -2412,6 +2412,9 @@ int plugin_dispatch_multivalue (value_list_t const *template, /* {{{ */
case DS_TYPE_DERIVE:
vl->values[0].derive = va_arg (ap, derive_t);
break;
+ case DS_TYPE_DDERIVE:
+ vl->values[0].dderive = va_arg (ap, dderive_t);
+ break;
default:
ERROR ("plugin_dispatch_multivalue: given store_type is incorrect.");
failed++;
diff --git a/src/daemon/plugin.h b/src/daemon/plugin.h
index 49edba2..96bd2f5 100644
--- a/src/daemon/plugin.h
+++ b/src/daemon/plugin.h
@@ -46,11 +46,13 @@
#define DS_TYPE_GAUGE 1
#define DS_TYPE_DERIVE 2
#define DS_TYPE_ABSOLUTE 3
+#define DS_TYPE_DDERIVE 4
#define DS_TYPE_TO_STRING(t) (t == DS_TYPE_COUNTER) ? "counter" : \
(t == DS_TYPE_GAUGE) ? "gauge" : \
(t == DS_TYPE_DERIVE) ? "derive" : \
(t == DS_TYPE_ABSOLUTE) ? "absolute" : \
+ (t == DS_TYPE_DDERIVE) ? "dderive" : \
"unknown"
@@ -85,6 +87,7 @@ typedef unsigned long long counter_t;
typedef double gauge_t;
typedef int64_t derive_t;
typedef uint64_t absolute_t;
+typedef double dderive_t;
union value_u
{
@@ -92,6 +95,7 @@ union value_u
gauge_t gauge;
derive_t derive;
absolute_t absolute;
+ dderive_t dderive;
};
typedef union value_u value_t;
diff --git a/src/daemon/types_list.c b/src/daemon/types_list.c
index 34c222c..ed0726a 100644
--- a/src/daemon/types_list.c
+++ b/src/daemon/types_list.c
@@ -79,6 +79,8 @@ static int parse_ds (data_source_t *dsrc, char *buf, size_t buf_len)
dsrc->type = DS_TYPE_DERIVE;
else if (strcasecmp (fields[1], "ABSOLUTE") == 0)
dsrc->type = DS_TYPE_ABSOLUTE;
+ else if (strcasecmp (fields[1], "DDERIVE") == 0)
+ dsrc->type = DS_TYPE_DDERIVE;
else
{
ERROR ("(fields[1] = %s) != (GAUGE || COUNTER || DERIVE || ABSOLUTE)", fields[1]);
diff --git a/src/daemon/utils_cache.c b/src/daemon/utils_cache.c
index 7c1fa41..3ab1b23 100644
--- a/src/daemon/utils_cache.c
+++ b/src/daemon/utils_cache.c
@@ -199,6 +199,11 @@ static int uc_insert (const data_set_t *ds, const value_list_t *vl,
ce->values_raw[i].absolute = vl->values[i].absolute;
break;
+ case DS_TYPE_DDERIVE:
+ ce->values_gauge[i] = NAN;
+ ce->values_raw[i].dderive = vl->values[i].dderive;
+ break;
+
default:
/* This shouldn't happen. */
ERROR ("uc_insert: Don't know how to handle data source type %i.",
@@ -444,6 +449,16 @@ int uc_update (const data_set_t *ds, const value_list_t *vl)
ce->values_raw[i].absolute = vl->values[i].absolute;
break;
+ case DS_TYPE_DDERIVE:
+ {
+ dderive_t diff = vl->values[i].dderive - ce->values_raw[i].dderive;
+
+ ce->values_gauge[i] = ((double) diff)
+ / (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
+ ce->values_raw[i].dderive = vl->values[i].dderive;
+ }
+ break;
+
default:
/* This shouldn't happen. */
pthread_mutex_unlock (&cache_lock);
diff --git a/src/daemon/utils_match.c b/src/daemon/utils_match.c
index 914b6e2..1dc5f79 100644
--- a/src/daemon/utils_match.c
+++ b/src/daemon/utils_match.c
@@ -216,6 +216,30 @@ static int default_callback (const char __attribute__((unused)) *str,
data->values_num++;
}
+ else if (data->ds_type & UTILS_MATCH_DS_TYPE_DDERIVE)
+ {
+ dderive_t value;
+ char *endptr = NULL;
+
+ if (matches_num < 2)
+ return (-1);
+
+ value = (dderive_t) strtod (matches[1], &endptr);
+ if (matches[1] == endptr)
+ return (-1);
+
+ if (data->ds_type & UTILS_MATCH_CF_DDERIVE_SET)
+ data->value.dderive = value;
+ else if (data->ds_type & UTILS_MATCH_CF_DDERIVE_ADD)
+ data->value.dderive += value;
+ else
+ {
+ ERROR ("utils_match: default_callback: obj->ds_type is invalid!");
+ return (-1);
+ }
+
+ data->values_num++;
+ }
else
{
ERROR ("utils_match: default_callback: obj->ds_type is invalid!");
diff --git a/src/daemon/utils_match.h b/src/daemon/utils_match.h
index a1d1002..68dbe41 100644
--- a/src/daemon/utils_match.h
+++ b/src/daemon/utils_match.h
@@ -35,10 +35,11 @@
* ^ <- Type bit
* ^^^^^^^^^^^^ <- Subtype bits
*/
-#define UTILS_MATCH_DS_TYPE_GAUGE 0x1000
-#define UTILS_MATCH_DS_TYPE_COUNTER 0x2000
-#define UTILS_MATCH_DS_TYPE_DERIVE 0x4000
-#define UTILS_MATCH_DS_TYPE_ABSOLUTE 0x8000
+#define UTILS_MATCH_DS_TYPE_GAUGE 0x01000
+#define UTILS_MATCH_DS_TYPE_COUNTER 0x02000
+#define UTILS_MATCH_DS_TYPE_DERIVE 0x04000
+#define UTILS_MATCH_DS_TYPE_ABSOLUTE 0x08000
+#define UTILS_MATCH_DS_TYPE_DDERIVE 0x10000
#define UTILS_MATCH_CF_GAUGE_AVERAGE 0x01
#define UTILS_MATCH_CF_GAUGE_MIN 0x02
@@ -59,6 +60,9 @@
#define UTILS_MATCH_CF_ABSOLUTE_ADD 0x02
#define UTILS_MATCH_CF_ABSOLUTE_INC 0x04
+#define UTILS_MATCH_CF_DDERIVE_SET 0x01
+#define UTILS_MATCH_CF_DDERIVE_ADD 0x02
+
/*
* Data types
*/
diff --git a/src/java.c b/src/java.c
index 47f4cd3..04d7dd2 100644
--- a/src/java.c
+++ b/src/java.c
@@ -307,6 +307,8 @@ static jobject ctoj_value_to_number (JNIEnv *jvm_env, /* {{{ */
return (ctoj_jlong_to_number (jvm_env, (jlong) value.derive));
if (ds_type == DS_TYPE_ABSOLUTE)
return (ctoj_jlong_to_number (jvm_env, (jlong) value.absolute));
+ else if (ds_type == DS_TYPE_DDERIVE)
+ return (ctoj_jlong_to_number (jvm_env, (jdouble) value.dderive));
else
return (NULL);
} /* }}} jobject ctoj_value_to_number */
@@ -1063,7 +1065,8 @@ static int jtoc_value (JNIEnv *jvm_env, /* {{{ */
class_ptr = (*jvm_env)->GetObjectClass (jvm_env, object_ptr);
- if (ds_type == DS_TYPE_GAUGE)
+ if ((ds_type == DS_TYPE_GAUGE)
+ || (ds_type == DS_TYPE_DDERIVE))
{
jdouble tmp_double;
@@ -1075,7 +1078,10 @@ static int jtoc_value (JNIEnv *jvm_env, /* {{{ */
"jtoc_double failed.");
return (-1);
}
- (*ret_value).gauge = (gauge_t) tmp_double;
+ if (ds_type == DS_TYPE_GAUGE)
+ (*ret_value).gauge = (gauge_t) tmp_double;
+ else if (ds_type == DS_TYPE_DDERIVE)
+ (*ret_value).dderive = (gauge_t) tmp_double;
}
else
{
diff --git a/src/perl.c b/src/perl.c
index 48374b6..6673e2e 100644
--- a/src/perl.c
+++ b/src/perl.c
@@ -216,6 +216,7 @@ struct {
{ "Collectd::DS_TYPE_GAUGE", DS_TYPE_GAUGE },
{ "Collectd::DS_TYPE_DERIVE", DS_TYPE_DERIVE },
{ "Collectd::DS_TYPE_ABSOLUTE", DS_TYPE_ABSOLUTE },
+ { "Collectd::DS_TYPE_DDERIVE", DS_TYPE_DDERIVE },
{ "Collectd::LOG_ERR", LOG_ERR },
{ "Collectd::LOG_WARNING", LOG_WARNING },
{ "Collectd::LOG_NOTICE", LOG_NOTICE },
@@ -283,7 +284,8 @@ static int hv2data_source (pTHX_ HV *hash, data_source_t *ds)
if ((DS_TYPE_COUNTER != ds->type)
&& (DS_TYPE_GAUGE != ds->type)
&& (DS_TYPE_DERIVE != ds->type)
- && (DS_TYPE_ABSOLUTE != ds->type)) {
+ && (DS_TYPE_ABSOLUTE != ds->type)
+ && (DS_TYPE_DDERIVE != ds->type)) {
log_err ("hv2data_source: Invalid DS type.");
return -1;
}
@@ -340,6 +342,8 @@ static size_t av2value (pTHX_ char *name, AV *array, value_t *value, size_t arra
value[i].derive = SvIV (*tmp);
else if (DS_TYPE_ABSOLUTE == ds->ds[i].type)
value[i].absolute = SvIV (*tmp);
+ else if (DS_TYPE_DDERIVE == ds->ds[i].type)
+ value[i].dderive = SvNV (*tmp);
}
else {
return 0;
@@ -658,6 +662,8 @@ static int value_list2hv (pTHX_ value_list_t *vl, data_set_t *ds, HV *hash)
val = newSViv (vl->values[i].derive);
else if (DS_TYPE_ABSOLUTE == ds->ds[i].type)
val = newSViv (vl->values[i].absolute);
+ else if (DS_TYPE_DDERIVE == ds->ds[i].type)
+ val = newSVnv (vl->values[i].dderive);
if (NULL == av_store (values, i, val)) {
av_undef (values);
diff --git a/src/python.c b/src/python.c
index 24046de..fe71162 100644
--- a/src/python.c
+++ b/src/python.c
@@ -54,7 +54,8 @@ static char get_ds_doc[] = "get_dataset(name) -> definition\n"
" name, type, min and max value.\n"
" 'name' is a string.\n"
" 'type' is a string that is equal to either DS_TYPE_COUNTER,\n"
- " DS_TYPE_GAUGE, DS_TYPE_DERIVE or DS_TYPE_ABSOLUTE.\n"
+ " DS_TYPE_GAUGE, DS_TYPE_DERIVE, DS_TYPE_ABSOLUTE,\n"
+ " or DS_TYPE_DDERIVE.\n"
" 'min' and 'max' are either a float or None.";
static char flush_doc[] = "flush([plugin][, timeout][, identifier]) -> None\n"
@@ -374,6 +375,8 @@ static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_li
PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
} else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) {
PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
+ } else if (ds->ds[i].type == DS_TYPE_DDERIVE) {
+ PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].dderive));
} else {
Py_BEGIN_ALLOW_THREADS
ERROR("cpy_write_callback: Unknown value type %d.", ds->ds[i].type);
@@ -1092,6 +1095,7 @@ static int cpy_init_python(void) {
PyModule_AddStringConstant(module, "DS_TYPE_GAUGE", DS_TYPE_TO_STRING(DS_TYPE_GAUGE));
PyModule_AddStringConstant(module, "DS_TYPE_DERIVE", DS_TYPE_TO_STRING(DS_TYPE_DERIVE));
PyModule_AddStringConstant(module, "DS_TYPE_ABSOLUTE", DS_TYPE_TO_STRING(DS_TYPE_ABSOLUTE));
+ PyModule_AddStringConstant(module, "DS_TYPE_DDERIVE", DS_TYPE_TO_STRING(DS_TYPE_DDERIVE));
return 0;
}
diff --git a/src/pyvalues.c b/src/pyvalues.c
index a7cb792..f634fd9 100644
--- a/src/pyvalues.c
+++ b/src/pyvalues.c
@@ -585,6 +585,13 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
Py_XDECREF(num);
}
break;
+ case DS_TYPE_DDERIVE:
+ num = PyNumber_Float(item); /* New reference. */
+ if (num != NULL) {
+ value[i].dderive = PyFloat_AsDouble(num);
+ Py_XDECREF(num);
+ }
+ break;
default:
free(value);
PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds[i].type, value_list.type);
@@ -694,6 +701,13 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
Py_XDECREF(num);
}
break;
+ case DS_TYPE_DDERIVE:
+ num = PyNumber_Float(item); /* New reference. */
+ if (num != NULL) {
+ value[i].dderive = PyFloat_AsDouble(num);
+ Py_XDECREF(num);
+ }
+ break;
default:
free(value);
PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds[i].type, value_list.type);
diff --git a/src/redis.c b/src/redis.c
index 7395ba0..f1b9c8d 100644
--- a/src/redis.c
+++ b/src/redis.c
@@ -354,6 +354,9 @@ static int redis_handle_query (redisContext *rh, redis_node_t *rn, redis_query_t
case DS_TYPE_ABSOLUTE:
val.gauge = (absolute_t)rr->integer;
break;
+ case DS_TYPE_DDERIVE:
+ val.dderive = (dderive_t)rr->integer;
+ break;
}
break;
case REDIS_REPLY_STRING:
diff --git a/src/rrdcached.c b/src/rrdcached.c
index 0425419..156f24b 100644
--- a/src/rrdcached.c
+++ b/src/rrdcached.c
@@ -87,7 +87,8 @@ static int value_list_to_string (char *buffer, int buffer_len,
if ((ds->ds[i].type != DS_TYPE_COUNTER)
&& (ds->ds[i].type != DS_TYPE_GAUGE)
&& (ds->ds[i].type != DS_TYPE_DERIVE)
- && (ds->ds[i].type != DS_TYPE_ABSOLUTE))
+ && (ds->ds[i].type != DS_TYPE_ABSOLUTE)
+ && (ds->ds[i].type != DS_TYPE_DDERIVE))
return (-1);
if (ds->ds[i].type == DS_TYPE_COUNTER)
@@ -104,11 +105,15 @@ static int value_list_to_string (char *buffer, int buffer_len,
status = ssnprintf (buffer + offset, buffer_len - offset,
":%"PRIi64, vl->values[i].derive);
}
- else /* if (ds->ds[i].type == DS_TYPE_ABSOLUTE) */ {
+ else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) {
status = ssnprintf (buffer + offset, buffer_len - offset,
":%"PRIu64, vl->values[i].absolute);
}
+ else /* if (ds->ds[i].type == DS_TYPE_DDERIVE) */ {
+ status = ssnprintf (buffer + offset, buffer_len - offset,
+ ":%f", vl->values[i].dderive);
+ }
if ((status < 1) || (status >= (buffer_len - offset)))
return (-1);
diff --git a/src/tail.c b/src/tail.c
index b8922ec..dbbed8e 100644
--- a/src/tail.c
+++ b/src/tail.c
@@ -120,6 +120,16 @@ static int ctail_config_add_match_dstype (ctail_config_match_t *cm,
else
cm->flags = 0;
}
+ else if (strncasecmp ("DDerive", ci->values[0].value.string, strlen ("DDerive")) == 0)
+ {
+ cm->flags = UTILS_MATCH_DS_TYPE_DDERIVE;
+ if (strcasecmp ("DDeriveSet", ci->values[0].value.string) == 0)
+ cm->flags |= UTILS_MATCH_CF_DDERIVE_SET;
+ else if (strcasecmp ("DDeriveAdd", ci->values[0].value.string) == 0)
+ cm->flags |= UTILS_MATCH_CF_DDERIVE_ADD;
+ else
+ cm->flags = 0;
+ }
else
{
cm->flags = 0;
diff --git a/src/target_scale.c b/src/target_scale.c
index 22af4e3..818635e 100644
--- a/src/target_scale.c
+++ b/src/target_scale.c
@@ -298,6 +298,17 @@ static int ts_config_set_double (double *ret, oconfig_item_t *ci) /* {{{ */
return (0);
} /* }}} int ts_config_set_double */
+static int ts_invoke_dderive (const data_set_t *ds, value_list_t *vl, /* {{{ */
+ ts_data_t *data, int dsrc_index)
+{
+ if (!isnan (data->factor))
+ vl->values[dsrc_index].dderive *= data->factor;
+ if (!isnan (data->offset))
+ vl->values[dsrc_index].dderive += data->offset;
+
+ return (0);
+} /* }}} int ts_invoke_dderive */
+
static int ts_config_add_data_source(ts_data_t *data, /* {{{ */
oconfig_item_t *ci)
{
@@ -477,6 +488,8 @@ static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
ts_invoke_derive (ds, vl, data, i);
else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
ts_invoke_absolute (ds, vl, data, i);
+ else if (ds->ds[i].type == DS_TYPE_DDERIVE)
+ ts_invoke_dderive (ds, vl, data, i);
else
ERROR ("Target `scale': Ignoring unknown data source type %i",
ds->ds[i].type);
diff --git a/src/utils_format_graphite.c b/src/utils_format_graphite.c
index e523420..a212356 100644
--- a/src/utils_format_graphite.c
+++ b/src/utils_format_graphite.c
@@ -70,6 +70,8 @@ static int gr_format_values (char *ret, size_t ret_len,
BUFFER_ADD ("%"PRIi64, vl->values[ds_num].derive);
else if (ds->ds[ds_num].type == DS_TYPE_ABSOLUTE)
BUFFER_ADD ("%"PRIu64, vl->values[ds_num].absolute);
+ else if (ds->ds[ds_num].type == DS_TYPE_DDERIVE)
+ BUFFER_ADD (DDERIVE_FORMAT, vl->values[ds_num].dderive);
else
{
ERROR ("gr_format_values plugin: Unknown data source type: %i",
diff --git a/src/utils_format_json.c b/src/utils_format_json.c
index 5b5fcdf..e45f6df 100644
--- a/src/utils_format_json.c
+++ b/src/utils_format_json.c
@@ -149,6 +149,13 @@ static int values_to_json (char *buffer, size_t buffer_size, /* {{{ */
BUFFER_ADD ("%"PRIi64, vl->values[i].derive);
else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
BUFFER_ADD ("%"PRIu64, vl->values[i].absolute);
+ else if (ds->ds[i].type == DS_TYPE_DDERIVE)
+ {
+ if(isfinite (vl->values[i].dderive))
+ BUFFER_ADD (JSON_DDERIVE_FORMAT, vl->values[i].dderive);
+ else
+ BUFFER_ADD ("null");
+ }
else
{
ERROR ("format_json: Unknown data source type: %i",
diff --git a/src/utils_format_json.h b/src/utils_format_json.h
index a3eda30..2091c7e 100644
--- a/src/utils_format_json.h
+++ b/src/utils_format_json.h
@@ -35,6 +35,10 @@
# define JSON_GAUGE_FORMAT GAUGE_FORMAT
#endif
+#ifndef JSON_DDERIVE_FORMAT
+# define JSON_DDERIVE_FORMAT DDERIVE_FORMAT
+#endif
+
int format_json_initialize (char *buffer,
size_t *ret_buffer_fill, size_t *ret_buffer_free);
int format_json_value_list (char *buffer,
diff --git a/src/utils_format_kairosdb.c b/src/utils_format_kairosdb.c
index 41055c7..f073d8c 100644
--- a/src/utils_format_kairosdb.c
+++ b/src/utils_format_kairosdb.c
@@ -200,6 +200,26 @@ static int values_to_kairosdb (char *buffer, size_t buffer_size, /* {{{ */
BUFFER_ADD (",");
BUFFER_ADD ("%"PRIu64, vl->values[ds_idx].absolute);
}
+ else if (ds->ds[ds_idx].type == DS_TYPE_DDERIVE)
+ {
+ if (isfinite (vl->values[ds_idx].dderive))
+ {
+ BUFFER_ADD ("[[");
+ BUFFER_ADD ("%"PRIu64, CDTIME_T_TO_MS (vl->time));
+ BUFFER_ADD (",");
+ BUFFER_ADD (JSON_DDERIVE_FORMAT, vl->values[ds_idx].dderive);
+ }
+ else
+ {
+ DEBUG ("utils_format_kairosdb: invalid vl->values[ds_idx].dderive for %s|%s|%s|%s|%s",
+ vl->plugin,
+ vl->plugin_instance,
+ vl->type,
+ vl->type_instance,
+ ds->ds[ds_idx].name);
+ return (-1);
+ }
+ }
else
{
ERROR ("format_kairosdb: Unknown data source type: %i",
diff --git a/src/utils_format_kairosdb.h b/src/utils_format_kairosdb.h
index 764b0b1..dc8ffab 100644
--- a/src/utils_format_kairosdb.h
+++ b/src/utils_format_kairosdb.h
@@ -35,6 +35,10 @@
# define JSON_GAUGE_FORMAT GAUGE_FORMAT
#endif
+#ifndef JSON_DDERIVE_FORMAT
+# define JSON_DDERIVE_FORMAT DDERIVE_FORMAT
+#endif
+
int format_kairosdb_initialize (char *buffer,
size_t *ret_buffer_fill, size_t *ret_buffer_free);
int format_kairosdb_value_list (char *buffer,
diff --git a/src/utils_rrdcreate.c b/src/utils_rrdcreate.c
index 884de8f..2f23d97 100644
--- a/src/utils_rrdcreate.c
+++ b/src/utils_rrdcreate.c
@@ -310,6 +310,8 @@ static int ds_get (char ***ret, /* {{{ */
type = "DERIVE";
else if (d->type == DS_TYPE_ABSOLUTE)
type = "ABSOLUTE";
+ else if (d->type == DS_TYPE_DDERIVE)
+ type = "DDERIVE";
else
{
ERROR ("rrdtool plugin: Unknown DS type: %i",
diff --git a/src/write_mongodb.c b/src/write_mongodb.c
index 8fb13c3..7b6e2e9 100644
--- a/src/write_mongodb.c
+++ b/src/write_mongodb.c
@@ -123,6 +123,8 @@ static bson *wm_create_bson (const data_set_t *ds, /* {{{ */
bson_append_long(ret, key, vl->values[i].derive);
else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
bson_append_long(ret, key, vl->values[i].absolute);
+ else if (ds->ds[i].type == DS_TYPE_DDERIVE)
+ bson_append_double(ret, key, vl->values[i].dderive);
else
assert (23 == 42);
}
diff --git a/src/write_riemann.c b/src/write_riemann.c
index f143723..4dbb259 100644
--- a/src/write_riemann.c
+++ b/src/write_riemann.c
@@ -371,6 +371,13 @@ wrr_value_to_event(struct riemann_host const *host, /* {{{ */
} else if (rates != NULL) {
riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_D, (double)rates[index],
RIEMANN_EVENT_FIELD_NONE);
+ } else if (ds->ds[index].type == DS_TYPE_DDERIVE) {
+ double metric;
+
+ metric = vl->values[index].dderive;
+
+ riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_D,
+ metric, RIEMANN_EVENT_FIELD_NONE);
} else {
int64_t metric;
diff --git a/src/write_sensu.c b/src/write_sensu.c
index 6cb4994..0c3a881 100644
--- a/src/write_sensu.c
+++ b/src/write_sensu.c
@@ -499,7 +499,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
return NULL;
}
}
- else {
+ else if (ds->ds[index].type == DS_TYPE_COUNTER) {
res = my_asprintf(&value_str, "%llu", vl->values[index].counter);
if (res == -1) {
free(ret_str);
@@ -507,6 +507,14 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
return NULL;
}
}
+ else /* if (ds->ds[index].type == DS_TYPE_DDERIVE) */ {
+ res = my_asprintf(&value_str, DDERIVE_FORMAT, vl->values[index].dderive);
+ if (res == -1) {
+ free(ret_str);
+ ERROR("write_sensu plugin: Unable to alloc memory");
+ return NULL;
+ }
+ }
}
// Generate the full service name
diff --git a/src/write_tsdb.c b/src/write_tsdb.c
index bf49ba5..8db0551 100644
--- a/src/write_tsdb.c
+++ b/src/write_tsdb.c
@@ -322,6 +322,8 @@ static int wt_format_values(char *ret, size_t ret_len,
BUFFER_ADD("%" PRIi64, vl->values[ds_num].derive);
else if (ds->ds[ds_num].type == DS_TYPE_ABSOLUTE)
BUFFER_ADD("%" PRIu64, vl->values[ds_num].absolute);
+ else if (ds->ds[ds_num].type == DS_TYPE_DDERIVE)
+ BUFFER_ADD(DDERIVE_FORMAT, vl->values[ds_num].dderive);
else
{
ERROR("format_values plugin: Unknown data source type: %i",
--
2.7.4
More information about the collectd
mailing list