# RRD graphing stuffs
# Wijnand 'tehmaze' Modderman - http://tehmaze.com
# BSD License

# To generate graphs, use this bash script:
"""
#! /bin/bash

# your RRA path
RRA=/path/to/gozerbot/rra

for x in $RRA/*.rrd; do
    NAM=`basename $x .rrd` 
    IMG=$NAM.gif
    echo $IMG
    rrdtool graph new_$IMG \
        --title "Number of $NAM" \
        --start -86400 \
        --width 600 \
        --color BACK#FFFFFF \
        --color SHADEA#FFFFFF \
        --color SHADEB#FFFFFF \
        --color CANVAS#CCCCCC \
        --color GRID#999999 \
        --color MGRID#666666 \
        --color FONT#000000 \
        --color FRAME#333333 \
        DEF:size=$x:entries:AVERAGE \
        AREA:size\#FF8888 \
        LINE2:size\#FF0000:$NAM
    if test $? -eq 0; then
        mv -f new_$IMG $IMG
    fi
done

rrdtool graph new_totals.gif \
    --title "Total numbers" \
    --start -86400 \
    --width 600 \
    --color BACK#FFFFFF \
    --color SHADEA#FFFFFF \
    --color SHADEB#FFFFFF \
    --color CANVAS#CCCCCC \
    --color GRID#999999 \
    --color MGRID#666666 \
    --color FONT#000000 \
    --color FRAME#333333 \
    DEF:aliases=$RRA/aliases.rrd:entries:AVERAGE \
    DEF:callbacks=$RRA/callbacks.rrd:entries:AVERAGE \
    DEF:commands=$RRA/cmnds.rrd:entries:AVERAGE \
    DEF:examples=$RRA/examples.rrd:entries:AVERAGE \
    DEF:fleet=$RRA/fleet.rrd:entries:AVERAGE \
    DEF:reafter=$RRA/reafter.rrd:entries:AVERAGE \
    DEF:rebefore=$RRA/rebefore.rrd:entries:AVERAGE \
    DEF:users=$RRA/users.rrd:entries:AVERAGE \
    LINE1:aliases\#FF0000:aliases \
    LINE1:callbacks\#FF4400:callbacks \
    LINE1:commands\#FF8800:commands \
    LINE1:examples\#88FF00:examples \
    LINE1:fleet\#FF00FF:fleet \
    LINE1:reafter\#00FF00:reafter \
    LINE1:rebefore\#00FF88:rebefore \
    LINE1:users\#0000FF:users
if test $? -eq 0; then
    mv -f new_totals.gif totals.gif
fi
"""

from gozerbot.generic import gozerpopen, rlog
from gozerbot.commands import cmnds
from gozerbot.examples import examples
from gozerbot.users import users
from gozerbot.redispatcher import rebefore, reafter
from gozerbot.aliases import aliases
from gozerbot.callbacks import callbacks
from gozerbot.plugins import plugins
from gozerbot.fleet import fleet
from gozerbot.plughelp import plughelp
from gozerbot.periodical import minutely, periodical
import os, sys
import time
try:
    import rrdtool
except ImportError:
    rlog(10, 'rrd', 'you need the rrdool python bindings')
    raise

graph = None

class RRD:
    RRA = 'rra' # path relative to your gozerbot root

    def __init__(self):
        if not os.path.isdir(self.RRA):
            os.mkdir(self.RRA)
            rlog(10, 'rrd', 'created RRA directory %s' % (os.path.abspath(self.RRA)))
   
    def ps_size(self):
        """ ps .. show ps line of the bot """
        args = ['ps', '-o', 'rss', str(os.getpid())]
        try:
            proces = gozerpopen(args)
        except Exception, ex:
            return 0
        data = proces.fromchild.readlines()
        returncode = proces.close()
        if returncode == 0:
            result = str(data[1]).strip().split()
            return int(result[0])
        else:
            return 0

    def plugsizes(self):
        """ call the size() function in all plugins """
        result = {}
        for i, j in plugins.plugs.iteritems():
            try:
                result['x_plugin_%s' % i] = j.size()
            except AttributeError:
                pass
        return result

    @minutely
    def create_graphs(self):
        datas = {
            'fleet': fleet.size(),
            'users': users.size(),
            'cmnds': cmnds.size(),
            'callbacks': callbacks.size(),
            'rebefore': rebefore.size(),
            'reafter': reafter.size(),
            'aliases': len(aliases.data),
            'examples': examples.size(),
            'memory': self.ps_size(),
        }
        datas.update(self.plugsizes())
        for name, size in datas.iteritems():
            self.fill_graph(name, size)
        del datas # cleanup

    def check_graph(self, name):
        fname = os.path.join(self.RRA, '%s.rrd' % name)
        if not os.path.isfile(fname):
            rrdtool.create(fname, 
                '-s 60',
                '-b %s' % str(int(time.time())),
                'DS:entries:GAUGE:120:0:1000000',
                'RRA:AVERAGE:0.5:1:576',
                'RRA:AVERAGE:0.5:6:672',
                'RRA:AVERAGE:0.5:24:732',
                'RRA:AVERAGE:0.5:144:1460'
                )
        return fname

    def fill_graph(self, name, size):
        fname = self.check_graph(name)
        v = str(size)
        #print 'fill_graph(', name, ', ', size, '):', fname
        sys.stdout.flush()
        try:
            rrdtool.update(fname, 'N:%s' % (v,))
        except rrdtool.error, e:
            rlog(10, 'rrd', 'failed to update %s: %s' % (fname, str(e)))

def init():
    global graph
    graph = RRD()
    graph.create_graphs()
    return 1

def shutdown():
    global graph
    periodical.kill()
    del graph

