p|r|b Project

Custom Search
A modular rrd browser for polling and graphing

How it works

Components

prb consists of a number of essential components that make the whole thing work.
  1. Basic LAMP provides the basic infrastructure
  2. rrdtool provides the utilities for creating round-robin databases, updating data, creating graphs and so on
  3. prb itself consists of two main parts:
    • the prb poller and updater: prbupdate. This is scheduled in crontab to poll devices (typically) every five minutes. It takes care of creating the .rrd files if necessary and updates them with the retrieved data.
    • the prb web front end: the scripts under www. This provides all the functionality for adding devices, adding polling configuration information for devices and so on. It also provides the browsing functionality to go through all the graphable information in a structured and hierarchical way.
The neat thing in this setup is that both the frontend and the backend are written in php, and they share a number of php classes to ensure they do the work together in a consistent manner.
Also, the class for polling, updating and graphing is extendable and each file is module which can be taylored individually. This approach is very simple, flexible and easy to learn.

How Modules Work

The most important class is the lib/Info.php class. It is extended by the lib/mods/modulename.php classes which contain specific details.

Here is an example module for port information (as in ethernet ports, etc):

Example module 'port.php' source code
<?php

 
Class port extends Info {

    var 
$moduleVars;

    function 
setVars() {
        
#
        # setup which vars are used by this module
        #
        
$this->moduleVars array_merge
            
$this->reqVars,
            array(
            
'community'   => 'req',
            
'ifIndex'     => 'req',
            
'ifDescr'     => 'opt',
            
'in'          => 'opt',
            
'out'         => 'opt',
            
'limit'       => 'opt',
            
'bandwidth'   => 'opt',
            
'connection'  => 'opt',
            
'router'      => 'opt',
            ));
    }

    function 
CreateDB() {

        
$this->createOpts array_merge(
            array ( 
            
"DS:input:COUNTER:600:U:U",
            
"DS:output:COUNTER:600:U:U"),
            
$this->stdrra);

        if( 
$this->debug ) {print "Creating $this->rrdFile...\n";}
        return 
rrd_create($this->rrdFile$this->createOptscount($this->createOpts));
    }

    function 
Update() {

        
$if  $this->ifIndex;
        
$in  snmpget($this->host$this->community".1.3.6.1.2.1.2.2.1.10.".$if);
        
$out snmpget($this->host$this->community".1.3.6.1.2.1.2.2.1.16.".$if);

        
$this->outtext "N:$in:$out";
        
$ret rrd_update($this->rrdFile,"N:$in:$out");
        if ( 
$ret == ) {
            
$err rrd_error();
            echo 
"ERROR occurred: $err\n";
        }
        return 
$ret;
    }

    function 
Graph($ext$time$w=W$h=H) {

        
$connection "COMMENT:\\l";
        if( 
$this->connection !== '' $connection "COMMENT:$this->connection\\l";
        
$graph array_merge(
        
$this->graphDefOpts, array (
        
"-w"$w"-h"$h,
        
"-t"$this->description,
        
"-v Bandwidth",
        
"-s ".$time,
        
"DEF:input=".$this->rrdFile.":input:AVERAGE",
        
"DEF:output=".$this->rrdFile.":output:AVERAGE",
        
"CDEF:inbits=input,8,*",
        
"CDEF:outbits=output,8,*",
        
$connection,
        
"COMMENT:\\s",
        
"AREA:inbits#00CC00:  Incomming traffic\\t",
        
"GPRINT:inbits:LAST:Current\\: %8.3lf %sbps\\t",
        
"GPRINT:inbits:MAX:Max\\: %8.3lf %sbps\\t",
        
"GPRINT:inbits:AVERAGE:Average\\: %8.3lf %sbps\\l",
        
"LINE2:outbits#0000FF:  Outgoing traffic\\t",
        
"GPRINT:outbits:LAST:Current\\: %8.3lf %sbps\\t",
        
"GPRINT:outbits:MAX:Max\\: %8.3lf %sbps\\t",
        
"GPRINT:outbits:AVERAGE:Average\\: %8.3lf %sbps\\l",
        
$this->lastUpdate())
        );

        
$ret =  rrd_graph$this->pngFilePre."-".$ext.".png"$graphcount($graph) );
    }
}
?>

First the variables required by this module are defined, indicating required and optional variables. Then the real work is done by the following functions:

CreateDB(); Update(); Graph();

In this example

  • CreateDB() defined the 'input' and 'output' datasources and creates the rrd database.
  • Update() does an snmpget() of the relevant OID's to gather the input and output Octets for the configured host and ifIndex.
  • And finally Graphs() defines exactly how the data should be displayed.
All together, packaged neatly in one class.

Rolling Your Own

Writing your own modules is very easy:
  • Copy an existing module, for instance the port.php file described above,
  • change the initial class call to reflect the module name (this MUST be the same as the filename without the .php extension).
  • Edit the different sections to get the functionality you need.
  • Tweak the Graph options for a sleek looking display!
That's all it takes...