]> git.ipfire.org Git - collecty.git/blobdiff - src/collecty/plugins/base.py
Allow getting the standard deviation of the plotted values
[collecty.git] / src / collecty / plugins / base.py
index ec91599aa6d56be43f1e6c717d8297697f7ef6c5..c1666b6b3474809d9b7ef90d78e95e0257de4f83 100644 (file)
@@ -23,6 +23,7 @@ import datetime
 import logging
 import math
 import os
+import re
 import rrdtool
 import tempfile
 import threading
@@ -30,9 +31,12 @@ import time
 import unicodedata
 
 from .. import locales
+from .. import util
 from ..constants import *
 from ..i18n import _
 
+DEF_MATCH = re.compile(r"C?DEF:([A-Za-z0-9_]+)=")
+
 class Timer(object):
        def __init__(self, timeout, heartbeat=1):
                self.timeout = timeout
@@ -437,6 +441,46 @@ class Object(object):
 
                return schema
 
+       @property
+       def rrd_schema_names(self):
+               ret = []
+
+               for line in self.rrd_schema:
+                       (prefix, name, type, lower_limit, upper_limit) = line.split(":")
+                       ret.append(name)
+
+               return ret
+
+       def make_rrd_defs(self, prefix=None):
+               defs = []
+
+               for name in self.rrd_schema_names:
+                       if prefix:
+                               p = "%s_%s" % (prefix, name)
+                       else:
+                               p = name
+
+                       defs += [
+                               "DEF:%s=%s:%s:AVERAGE" % (p, self.file, name),
+                       ]
+
+               return defs
+
+       def get_stddev(self, interval=None):
+               args = self.make_rrd_defs()
+
+               # Add the correct interval
+               args += ["--start", util.make_interval(interval)]
+
+               for name in self.rrd_schema_names:
+                       args += [
+                               "VDEF:%s_stddev=%s,STDEV" % (name, name),
+                               "PRINT:%s_stddev:%%lf" % name,
+                       ]
+
+               x, y, vals = rrdtool.graph("/dev/null", *args)
+               return dict(zip(self.rrd_schema_names, vals))
+
        def execute(self):
                if self.collected:
                        raise RuntimeError("This object has already collected its data")
@@ -478,15 +522,6 @@ class GraphTemplate(object):
        # Extra arguments passed to rrdgraph.
        rrd_graph_args = []
 
-       intervals = {
-               None   : "-3h",
-               "hour" : "-1h",
-               "day"  : "-25h",
-               "month": "-30d",
-               "week" : "-360h",
-               "year" : "-365d",
-       }
-
        # Default dimensions for this graph
        height = GRAPH_DEFAULT_HEIGHT
        width  = GRAPH_DEFAULT_WIDTH
@@ -555,16 +590,32 @@ class GraphTemplate(object):
                        if self.upper_limit is not None:
                                args += ["--upper-limit", self.upper_limit]
 
-               try:
-                       interval = self.intervals[interval]
-               except KeyError:
-                       interval = "end-%s" % interval
-
                # Add interval
-               args += ["--start", interval]
+               args += ["--start", util.make_interval(interval)]
 
                return args
 
+       def _add_vdefs(self, args):
+               ret = []
+
+               for arg in args:
+                       ret.append(arg)
+
+                       # Search for all DEFs and CDEFs
+                       m = re.match(DEF_MATCH, "%s" % arg)
+                       if m:
+                               name = m.group(1)
+
+                               # Add the VDEFs for minimum, maximum, etc. values
+                               ret += [
+                                       "VDEF:%s_cur=%s,LAST" % (name, name),
+                                       "VDEF:%s_avg=%s,AVERAGE" % (name, name),
+                                       "VDEF:%s_max=%s,MAXIMUM" % (name, name),
+                                       "VDEF:%s_min=%s,MINIMUM" % (name, name),
+                               ]
+
+               return ret
+
        def get_object(self, *args, **kwargs):
                return self.plugin.get_object(*args, **kwargs)
 
@@ -597,21 +648,21 @@ class GraphTemplate(object):
                args = self._make_command_line(interval, **kwargs)
 
                self.log.info(_("Generating graph %s") % self)
-               self.log.debug("  args: %s" % args)
 
-               object_files = self.get_object_files()
+               #object_files = self.get_object_files()
 
-               for item in self.rrd_graph:
-                       try:
-                               args.append(item % object_files)
-                       except TypeError:
-                               args.append(item)
+               if self.object:
+                       args += self.object.make_rrd_defs()
 
-                       self.log.debug("  %s" % args[-1])
+               args += self.rrd_graph
+               args = self._add_vdefs(args)
 
                # Convert arguments to string
                args = [str(e) for e in args]
 
+               for arg in args:
+                       self.log.debug("  %s" % arg)
+
                with Environment(self.timezone, self.locale.lang):
                        graph = rrdtool.graphv("-", *args)