--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rrdweb/backend.py Tue Jan 25 01:28:06 2011 +0200
@@ -0,0 +1,92 @@
+from rrdweb import rrd
+
+import operator
+
+def host_def (idx, name, dir, ds_in, ds_out, cf) :
+ """
+ VDEFs for given host, giving its avg/max values:
+
+ DEF:in/out_{idx}
+ CDEFtraf_{idx}
+ VDEF:avg/max_{idx}
+ PRINT:{idx} avg/max {value}
+ """
+
+ params = dict(
+ dir=dir, ds_in=ds_in, ds_out=ds_out, cf=cf,
+ idx=idx, rrd='%s/%s.rrd' % (dir, name)
+ )
+
+ return [
+ # in/out bandwidth in bytes/s
+ 'DEF:in_%(idx)d=%(rrd)s:%(ds_in)s:%(cf)s' % params,
+ 'DEF:out_%(idx)d=%(rrd)s:%(ds_out)s:%(cf)s' % params,
+
+ # total traffic in bits/s
+ 'CDEF:traf_%(idx)d=in_%(idx)d,out_%(idx)d,+,8,*' % params,
+
+ # average + maximum values
+ 'VDEF:avg_%(idx)d=traf_%(idx)d,AVERAGE' % params,
+ 'VDEF:max_%(idx)d=traf_%(idx)d,MAXIMUM' % params,
+
+ # output
+ 'PRINT:avg_%(idx)d:%(idx)d avg %%lf' % params,
+ 'PRINT:max_%(idx)d:%(idx)d max %%lf' % params,
+ ]
+
+def parse_report (rrds, lines) :
+ """
+ Parse the report output into a [ (name, avg, max) ] list
+ """
+
+ # idx values by type
+ data = {
+ 'avg': {},
+ 'max': {},
+ }
+
+ # interpret output
+ for line in lines :
+ # parse
+ idx, type, value = line.split()
+
+ # convert
+ idx = int(idx)
+ value = float(value)
+
+ # store
+ data[type][idx] = value
+
+ # build into name : (values) dict
+ return [
+ (
+ (name, data['avg'][idx], data['max'][idx])
+ ) for idx, name in enumerate(rrds)
+ ]
+
+def calc_top_hosts (dir, rrds, ds_in, ds_out, period='15m', count=5, cf='AVERAGE') :
+ """
+ Return the list of top-N rrd's in the given dir, sorted by total in/out bandwidth average over the given period.
+ """
+
+ # vdefs for hosts, avg/max_<idx> in bits/s + prints
+ defs = [stmt for idx, name in enumerate(rrds) for stmt in host_def(idx, name, dir, ds_in, ds_out, cf)]
+
+ # execute
+ _, _, output, _ = rrd.graph(False, *defs, start=('-%s' % period))
+
+ # parse
+ data = parse_report(rrds, output)
+
+ # sort for top-N avg
+ data.sort(key=operator.itemgetter(1))
+ top_avg = data[:count]
+
+ # sort for top-N max
+ data.sort(key=operator.itemgetter(2))
+ top_max = data[:count]
+
+ # merge hosts (we lose sorting order)
+ return set(host for host, avg, max in top_avg + top_max)
+
+