rrdweb/backend.py
author Tero Marttila <terom@fixme.fi>
Tue, 25 Jan 2011 01:28:06 +0200
changeset 32 47e977c23ba2
permissions -rw-r--r--
implement rendering of pmacct rrd graphs, and a dir/top.png feature
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)