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)