Hello.
Having written a method for calculating standard deviation using CDEFs
and VDEFs, I decided that I'd patch rrdtool to have an STDEV aggregation
function for VDEF.
Here how I calculated it with VDEFs and CDEFs:
rrdtool graph /dev/null \
DEF:01min=load.rrd:01min:AVERAGE \
VDEF:01min_mean=01min,AVERAGE
CDEF:01min_deviation=01min,01min_mean,- \
CDEF:01min_s_deviation=01min_deviation,01min_deviation,* \
VDEF:01min_ms_deviation=01min_s_deviation,AVERAGE \
CDEF:01min_rms_deviation=01min,0,*,01min_ms_deviation,SQRT,+ \
VDEF:01min_stdev=01min_rms_deviation,FIRST \
PRINT:01min_stdev:%lf
Rather longwinded -- maybe I could have done it a bit better?
So I thought a patch would be easier, and it wasn't so hard, so here it
is. It patches OK against the latest SVN snapshot (1.2.99907080300),
but not against the version shipped with Debian stable (1.2.15) --
things have moved around quite a bit since then.
Best wishes,
--
Patrick Cherry Bytemark Hosting Support
http://www.bytemark.co.uk/
tel: +44 (0) 845 004 3 004
diff --unified --recursive rrdtool-1.2.99907080300/CONTRIBUTORS rrdtool/CONTRIBUTORS
--- rrdtool-1.2.99907080300/CONTRIBUTORS 2007-09-02 22:01:17.000000000 +0000
+++ rrdtool/CONTRIBUTORS 2007-09-03 22:16:00.000000000 +0000
@@ -38,6 +38,7 @@
Mike Slifcak <slif with bellsouth.net> many rrdtool-1.1.x fixes
Oleg Cherevko <olwi with icyb.kiev.ua>
Otmar Lendl <O.Lendl with Austria.EU.net> (lots of bugfixes)
+Patrick Cherry <patrick with bytemark.co.uk>
Paul Joslin <Paul.Joslin with sdrc.com>
Peter Speck <speck with vitality.dk> eps/svg/pdf file format code in rrdtool-1.x
Peter Stamfest <peter with stamfest.at> initial multi-thread support
diff --unified --recursive rrdtool-1.2.99907080300/doc/rrdgraph_rpn.pod rrdtool/doc/rrdgraph_rpn.pod
--- rrdtool-1.2.99907080300/doc/rrdgraph_rpn.pod 2007-09-02 22:01:16.000000000 +0000
+++ rrdtool/doc/rrdgraph_rpn.pod 2007-09-03 22:20:31.000000000 +0000
@@ -257,6 +257,12 @@
Example: C<VDEF:avg=mydata,AVERAGE>
+=item STDEV
+
+Returns the standard deviation of the values.
+
+Example: C<VDEF:stdev=mydata,STDEV>
+
=item LAST, FIRST
Return the last/first value including its time. The time for
diff --unified --recursive rrdtool-1.2.99907080300/src/rrd_graph.c rrdtool/src/rrd_graph.c
--- rrdtool-1.2.99907080300/src/rrd_graph.c 2007-09-02 22:01:15.000000000 +0000
+++ rrdtool/src/rrd_graph.c 2007-09-03 22:06:33.000000000 +0000
@@ -4285,6 +4285,8 @@
gdes->vf.op = VDEF_MAXIMUM;
else if (!strcmp("AVERAGE", func))
gdes->vf.op = VDEF_AVERAGE;
+ else if (!strcmp("STDEV", func))
+ gdes->vf.op = VDEF_STDEV;
else if (!strcmp("MINIMUM", func))
gdes->vf.op = VDEF_MINIMUM;
else if (!strcmp("TOTAL", func))
@@ -4324,6 +4326,7 @@
break;
case VDEF_MAXIMUM:
case VDEF_AVERAGE:
+ case VDEF_STDEV:
case VDEF_MINIMUM:
case VDEF_TOTAL:
case VDEF_FIRST:
@@ -4412,9 +4415,11 @@
}
break;
case VDEF_TOTAL:
+ case VDEF_STDEV:
case VDEF_AVERAGE:{
int cnt = 0;
double sum = 0.0;
+ double average = 0.0;
for (step = 0; step < steps; step++) {
if (finite(data[step * src->ds_cnt])) {
@@ -4426,9 +4431,19 @@
if (dst->vf.op == VDEF_TOTAL) {
dst->vf.val = sum * src->step;
dst->vf.when = 0; /* no time component */
- } else {
+ } else if (dst->vf.op == VDEF_AVERAGE){
dst->vf.val = sum / cnt;
dst->vf.when = 0; /* no time component */
+ } else {
+ average = sum / cnt;
+ sum = 0.0;
+ for (step=0;step<steps;step++) {
+ if (finite(data[step*src->ds_cnt])) {
+ sum += pow((data[step*src->ds_cnt] - average),2.0);
+ };
+ }
+ dst->vf.val = pow(sum / cnt,0.5);
+ dst->vf.when = 0; /* no time component */
};
} else {
dst->vf.val = DNAN;
diff --unified --recursive rrdtool-1.2.99907080300/src/rrd_graph.h rrdtool/src/rrd_graph.h
--- rrdtool-1.2.99907080300/src/rrd_graph.h 2007-09-02 22:01:15.000000000 +0000
+++ rrdtool/src/rrd_graph.h 2007-09-03 22:00:46.000000000 +0000
@@ -54,6 +54,7 @@
VDEF_MAXIMUM = 0 /* like the MAX in (G)PRINT */
, VDEF_MINIMUM /* like the MIN in (G)PRINT */
, VDEF_AVERAGE /* like the AVERAGE in (G)PRINT */
+ , VDEF_STDEV /* the standard deviation */
, VDEF_PERCENT /* Nth percentile */
, VDEF_TOTAL /* average multiplied by time */
, VDEF_FIRST /* first non-unknown value and time */
_______________________________________________
rrd-developers mailing list
[email protected]
https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers