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

Reply via email to