summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 8694810)
raw | patch | inline | side by side (parent: 8694810)
author | oetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa> | |
Wed, 14 Jan 2009 07:22:09 +0000 (07:22 +0000) | ||
committer | oetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa> | |
Wed, 14 Jan 2009 07:22:09 +0000 (07:22 +0000) |
NEWS | patch | blob | history | |
doc/rrdgraph_rpn.pod | patch | blob | history | |
src/rrd_graph.c | patch | blob | history | |
src/rrd_graph.h | patch | blob | history |
index b31f0fdaf079d460feb24cb403107c4ba75a19bd..2c26f685c185ac4d80dd134e3a884c5516a1006b 100644 (file)
--- a/NEWS
+++ b/NEWS
-------
* no more spaces in output
* additional option: --header {none,xsd,dtd}
+
+RRDgraph
+--------
+* VDEF PERCENTNAN (PRECENT that ignores NAN)
diff --git a/doc/rrdgraph_rpn.pod b/doc/rrdgraph_rpn.pod
index 21661ba6f7138646909bb1f5e6a9ade92c7bd4c7..de44c0bde1dcd8cfd1c83e8b8cb974e4e4b340e3 100644 (file)
--- a/doc/rrdgraph_rpn.pod
+++ b/doc/rrdgraph_rpn.pod
Example: C<VDEF:total=mydata,TOTAL>
-=item PERCENT
+=item PERCENT, PERCENTNAN
This should follow a B<DEF> or B<CDEF> I<vname>. The I<vname> is popped,
another number is popped which is a certain percentage (0..100). The
data set is then sorted and the value returned is chosen such that
I<percentage> percent of the values is lower or equal than the result.
+For PERCENTNAN I<Unknown> values are ignored, but for PERCENT
I<Unknown> values are considered lower than any finite number for this
purpose so if this operator returns an I<unknown> you have quite a lot
of them in your data. B<Inf>inite numbers are lesser, or more, than the
(NaN E<lt> -INF E<lt> finite values E<lt> INF)
Example: C<VDEF:perc95=mydata,95,PERCENT>
+ C<VDEF:percnan95=mydata,95,PERCENTNAN>
=item LSLSLOPE, LSLINT, LSLCORREL
diff --git a/src/rrd_graph.c b/src/rrd_graph.c
index 613446ff0e3f6db6fc838f2e568395b74615cf89..40539b3cc0683df30e39033eb2df4d0e8d566353 100644 (file)
--- a/src/rrd_graph.c
+++ b/src/rrd_graph.c
}
if (!strcmp("PERCENT", func))
gdes->vf.op = VDEF_PERCENT;
+ else if (!strcmp("PERCENTNAN", func))
+ gdes->vf.op = VDEF_PERCENTNAN;
else if (!strcmp("MAXIMUM", func))
gdes->vf.op = VDEF_MAXIMUM;
else if (!strcmp("AVERAGE", func))
};
switch (gdes->vf.op) {
case VDEF_PERCENT:
+ case VDEF_PERCENTNAN:
if (isnan(param)) { /* no parameter given */
rrd_set_error
("Function '%s' needs parameter in VDEF '%s'\n",
printf("DEBUG: %3li:%10.2f %c\n",
step, array[step], step == field ? '*' : ' ');
#endif
+ }
+ break;
+ case VDEF_PERCENTNAN:{
+ rrd_value_t *array;
+ int field;
+ /* count number of "valid" values */
+ int nancount=0;
+ for (step = 0; step < steps; step++) {
+ if (!isnan(data[step * src->ds_cnt])) { nancount++; }
+ }
+ /* and allocate it */
+ if ((array = (rrd_value_t*)malloc(nancount * sizeof(double))) == NULL) {
+ rrd_set_error("malloc VDEV_PERCENT");
+ return -1;
+ }
+ /* and fill it in */
+ field=0;
+ for (step = 0; step < steps; step++) {
+ if (!isnan(data[step * src->ds_cnt])) {
+ array[field] = data[step * src->ds_cnt];
+ field++;
+ }
+ }
+ qsort(array, nancount, sizeof(double), vdef_percent_compar);
+ field = (nancount - 1) * dst->vf.param / 100;
+ dst->vf.val = array[field];
+ dst->vf.when = 0; /* no time component */
+ free(array);
}
break;
case VDEF_MAXIMUM:
diff --git a/src/rrd_graph.h b/src/rrd_graph.h
index 25e9db227c03fa3ca242cd5e83ef23ae413742db..cc36c256eb4a3526096ae9c541b52a6dbed56d28 100644 (file)
--- a/src/rrd_graph.h
+++ b/src/rrd_graph.h
, VDEF_LSLSLOPE /* least squares line slope */
, VDEF_LSLINT /* least squares line y_intercept */
, VDEF_LSLCORREL /* least squares line correlation coefficient */
+ , VDEF_PERCENTNAN /* Nth percentile ignoring NAN*/
};
enum text_prop_en {
TEXT_PROP_DEFAULT = 0, /* default settings */