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 <[email protected]> --- 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 _______________________________________________ collectd mailing list [email protected] https://mailman.verplant.org/listinfo/collectd
