General Code Structure
Copying existing code
Before using an existing piece of code as an example or template, check the age of the code in SVN. There are many places in the code where we have found better and more efficient ways of doing things as time goes on, but we don't always have time to update the old code.
A good example is in the graphing system, please only copy the newer graph definitions which use the graph templates, not the old ones which define the graph manually.
This is especially important in the poller and discovery modules, where the same thing is done in several different ways depending upon when it was written.
If in doubt, ask on the Mailing List or IRC to find out what the current recommended way of doing a task is.
We have created generic functions for rrdtool access. This allows us to globally support specific paths, options, or features such as rrdcached, and easy debugging.
The functions are in
The most important functions include
We have incorporated and modified dbFacile, which is a "frontend" for MySQL queries with automatic escaping etc. This means we need to be less bothered by SQL injection, and allows us to easily print queries when debugging, without needing code for that anywhere.
Commonly used functions include
dbDelete(). In many instances we have further abstracted data retrieval from the database with per-entity
build_*_query() functions which will build a query to fetch data from MySQL from a
dbFetchRows($sql, $parameters = array()) dbFetchCell($sql, $parameters = array()) dbUpdate($data, $table, $where = null, $parameters = array()) dbInsert($data, $table) dbDelete($table, $where = null, $parameters = array())
parameters array is an array of values substituted into the
$where string during processing. A value can be passed to MySQL without escaping by wrapping it in an
array(), for example array(array('NULL')) would pass the keyword NULL, rather than the text string 'NULL'.
Here are some example queries :
dbFetchRows('SELECT * FROM ports WHERE device_id = ?', array($device['device_id'])); dbUpdate(array('last_discovered' => array('NULL')), 'devices', '`device_id` = ?', array($device['device_id'])); dbDelete('device_graphs', "`device_id` = ? AND `graph` = ?", array($device['device_id'], $graph)); dbInsert(array('device_id' => $device['device_id'], 'graph' => $graph, 'enabled' => $value), 'device_graphs'); dbFetchCell("SELECT COUNT(*) FROM `ports` WHERE `device_id` = ? AND `ifType` = 'adsl'", array($device['device_id']));
The database API has recently been modified to support PHP's
mysqli module alongside the now-deprecated
We have created generic functions for SNMP calls. This allows us to transparantly run v1, 2c or 3 queries, do bulkwalk or not, set specific retries or timeouts, depending on the device configuration, and parse the results into different sorts of arrays, without needing to write code for this time and time again.
The functions are in
This file gets included first, and contains all configuration statements you can change. Do not change this file directly! It'll mess up your upgrades. Add entries you wish to override to
This file starts out small with things you need to configure, and will grow whenever you want to change one of the
defaults.inc.php settings away from its default. Note that if something is an array in defaults, just adding a field to it (eg snmp community setting) will not erase the defaults, but just add to them.
This file should not be changed unless developing. It contains definitions, settings and some compatibility setting code for deprecated settings. Graph titles, modules to be loaded, etc. are configured here, as are settings (icon, group, description, etc) for device types.
Discovery is started from
discovery.php in the Observium root directory. It runs discovery modules, which finds various things on configured devices.
For some modules, such as
OSPF and others, discovery is done during the polling, as the data is coming in anyway, so there is no point in having separate discovery code.
In a lot of instances actually discovering entities during discovery is an anachronism, as it's more convenient and efficient to add/remove things from the database in the poller because it walks the entire SNMP relevant table regardless and and we're slowly modifying the code to do this, like the ports poller and netscaler pollers.
The discovery system has an array
$config['discovery_modules'] which defines all modules to run during discovery, if the value is 1. You can override this for the entire Observium system in
config.inc.php, or per-device in the settings tab. A module needs to be in this array to be able to run.
The key in the array is the filename in
includes/discovery/ (followed by .inc.php).
Finding new things
TBD: discover_* functions
Polling is done through
poller.php, which calls
poll_device() for every device specified to be polled through the commandline options.
Similarly to the discovery module system (see above), the poller also has modules which can be enabled or disabled globally and per-device.
TBD: explain ports poller, also discovered here, etc.
Port type classification
See Interface Description Parsing - which file is included to to this depends on the configuration setting
After connecting to the agent, the poller receives a block of data, set into different sections indicated by
We parse some section names in
includes/polling/unix-agent.inc.php, or when the section name matches
app-appname, we include
includes/polling/applications/appname.inc.php if it exists.
When a sensor is found,
discover_sensor() is run, just like through discovery. The sensors are added to
$agent_sensors, which is later used to check which sensors can be removed (if they're not in agent_sensors, but they are in the database, they're gone and should be deleted).
Similar to the agent, IPMI sensors are discovered at polling time, and are stored in
$ipmi_sensors, also to be able to delete sensors that are gone at the end of the polling cycle.
The Observium web user interface is primarily constructed from a heavily modified hybrid Bootstrap ⅔ CSS framework. We've modified and extended the original Bootstrap 2 framework to include additional styles and partially merged Bootstrap 3 changes where they were beneficial to us.
TBD: top bar, menu, caching queries etc
TBD: auth modules usage, link to auth modules page, configuration and consequences
TBD: paths, includes, etc. debug