Skip to content

Adding support for a new MIB

Adding support for a new MIB to Observium requires writing code and/or definitions to describe the contents of the MIB and the entities to be collected. The MIB itself assists in this, but isn't sufficient by itself.

Writing MIB definitions and code can be relatively straight forward or it can be quite complex, depending upon the structure and design of the MIB. Support for sensors and other entities can be quite straightforward on well-designed MIBs.

Adding a MIB definition

As an example we'll add support for the UEC-STARLINE-MIB, a MIB used for Universal Electronic Corporation devices, containing several power-related sensors and counters.

First we need to check if there is already a directory for this vendor's MIBs and create one if there isn't. Then we need to place the MIB(s) in this directory and check if there's an Observium include file for this vendor's MIBs, and again create if necessary.

For this UEC MIB, the correct place would be mibs/uec/ in the Observium directory and the correct definition filename would be includes/definitions/mibs/

Once the MIBs are in place, you can create an initial definition for the MIB, like below:

$config['mibs'][$mib]['enable'] = 1;
$config['mibs'][$mib]['mib_dir'] = 'uec';
$config['mibs'][$mib]['identity_num'] = '.';
$config['mibs'][$mib]['descr'] = 'MIB module for managing measurement and control devices produced by the Universal Electric Corporation.';

This data should be fairly self-explanatory. The description field can often be copied from the module description near the top of the MIB file:

--   Universal Electric Corp.
--   STARLINE measurement and control devices MIB




      "MIB module for managing measurement and control devices
       produced by the Universal Electric Corporation."

The module identity can be determined using a number of different methods. Easiest is probably to use snmptranslate to find the OID that correspnds to the MODULE-IDENTITY:

root@dev:/opt/observium# snmptranslate -Pu -Tso -M mibs/uec/:mibs/rfc -m UEC-STARLINE-MIB

Here we can see that the uecStarline OID is a child of enterprises, and has the OID of . This could also be obtained from other modules which are children of enterprises by looking at the end of the MODULE-IDENTITY entry, after the REVISION sections:

    ::= { enterprises 35774 }

Associating a MIB to an OS

A MIB can be assigned to an OS by adding it to the OSes list of MIBs, this is done in the OS's definition section, in this case in includes/definitions/, this may be a vendor-specific file such as includes/definitions/os/

$os = "uec-starline";
$config['os'][$os]['mibs'][]                = "UEC-STARLINE-MIB";

This instructs the poller and discovery processes to use any definitions or files related to this MIB during polling and discovery.

Collecting an SNMPwalk of the MIB

Before we start extracting data from the MIB, we need to see what data is in there. You can use the commandline snmpwalk tools for this. A simple way is to snmpwalk the MIB's base oid. You can adjust the command below with the MIB names and directories you've already used. An SNMPv3 configuration will be more complex, and will require you to set the correct options.

We'll pipe this to a text file, uec-starline-mib.txt` so we don't have to keep walking the table.

snmpwalk -v2c -c <community> -M mibs/rfc:mibs/uec> -m UEC-STARLINE-MIB . > uec-starline-mib.txt

Extracting device metadata from the MIB

Some MIBs contain device-level metadata such as serial and uptime. These can be defined in the MIB definition.

UEC-STARLINE-MIB::cpmAcDeviceName.0 = STRING: FlexLab Busway Meter
UEC-STARLINE-MIB::cpmAcDeviceLocation.0 = STRING: FlexLab
UEC-STARLINE-MIB::cpmAcDeviceId.0 = STRING: 01
UEC-STARLINE-MIB::cpmAcModelNumber.0 = STRING: M43D
UEC-STARLINE-MIB::cpmAcSerialNumber.0 = STRING: 0008xxx
UEC-STARLINE-MIB::cpmAcCatalogNumber.0 = STRING: UF250T5C4S-SLSN-0100C-BLU0-M43D3
UEC-STARLINE-MIB::cpmAcFirmwareVersion.0 = STRING: M22276-116 v3.87

From the above SNMP walk we can use the serial number, model number and firmware version data.

$config['mibs'][$mib]['serial'][] = array('oid' => 'cpmAcSerialNumber.0');
$config['mibs'][$mib]['version'][] = array('oid' => 'cpmAcFirmwareVersion.0');
$config['mibs'][$mib]['hardware'][] = array('oid' => 'cpmAcModelNumber.0');

Once these are configured on the MIB, they'll be collected and used on any device whos OS as this MIB assigned to it.

Adding a Sensor

Adding a sensor is similar, but a little more involved. To add a simple sensor we'll take this one from the walk as an example:

UEC-STARLINE-MIB::cpmAcInfTotLineCurrDemand.0 = STRING: 11.55 Amps (rms)

We can look in the MIB for more details on this OID. It can be helpful to use a graphical MIB browser for this, but just looking in the text file itself is sufficient.

        cpmAcInfTotLineCurrDemand  OBJECT-TYPE
            SYNTAX      DisplayString
            UNITS       "amps per demand interval"
            MAX-ACCESS  read-write
            STATUS      current
                "The current demand of this line."
            ::= { cpmAcInfeedLineEntry 9 }

This is a quite straightforward sensor, as it's scalar (the index is 0) and not part of a table, and it's returning its value in base units. We can add it like this

We can set a static description, and can obtain the numeric OID by using snmptranslate or snmpget to make sure the value matches. -On tells snmpwalk to return numeric indexes.

root@dev:/opt/observium# snmpwalk -v2c -c starline -M mibs/rfc:mibs/uec/ -m ALL -On cpmAcInfTotLineCurrDemand
. = STRING: 11.55 Amps (rms)

The oid_num element requires the oid without the index part, so we remove the .0.

$config['mibs'][$mib]['sensor'][] = array('oid' => 'cpmAcInfTotLineCurrDemand',
                                          'class' => 'current',
                                          'descr' => 'Infeed Total',
                                          'oid_num' => '.');

We can also add sensors from tables, automatically pulling dynamic descritptions from indexes or other oids. We can use a similar OID as an example:

cpmAcInfeedLineIndex.line1 = INTEGER: line1(1)
cpmAcInfeedLineIndex.line2 = INTEGER: line2(2)
cpmAcInfeedLineIndex.line3 = INTEGER: line3(3)
cpmAcInfeedLineIndex.neutralC = INTEGER: neutralC(4)
cpmAcInfeedLineIndex.neutralM = INTEGER: neutralM(5)
cpmAcInfLineCurrent.line1 = STRING: 13.04 amps (rms)
cpmAcInfLineCurrent.line2 = STRING: 11.19 amps (rms)
cpmAcInfLineCurrent.line3 = STRING: 10.26 amps (rms)
cpmAcInfLineCurrent.neutralC = STRING: 0.06 amps (rms)
cpmAcInfLineCurrent.neutralM = STRING: 9999.99 amps (rms)

In this output we can see that the MIB provides the text version of the index in cpmAcInfeedLineIndex as a value we can use as a description, and it seem that the MIB uses 9999.99 as an "invalid" value, so we can try to screen this out.

$config['mibs'][$mib]['sensor'][] = array('oid' => 'cpmAcInfLineCurrent',
                                          'class' => 'current',
                                          'oid_descr' => 'cpmAcInfeedLineIndex', 
                                          'descr' => 'Infeed %oid_descr%',
                                          'oid_num' => '.',
                                          'invalid' => 9999.99);

Testing the sensor definition

Once you've created a definition, you can test it using discovery using ./discovery.php -h <device_id> -m sensors

If you've created it correctly you should see the MIB being called during the sensor discovery process, and the OIDs defined being checked.

root@dev:/opt/observium# ./discovery.php -h 780 -m sensors

  ___   _                              _
 / _ \ | |__   ___   ___  _ __ __   __(_) _   _  _ __ ___
| | | || '_ \ / __| / _ \| '__|\ \ / /| || | | || '_ ` _ \
| |_| || |_) |\__ \|  __/| |    \ V / | || |_| || | | | | |
 \___/ |_.__/ |___/ \___||_|     \_/  |_| \__,_||_| |_| |_|
                          Observium Professional 22.4.11928

#####  Starting discovery run at 2022-04-04 14:37:26  #####

##### [780]  #####

 o OS Type              uec-starline
 o SNMP Version         v2c
 o Last discovery       2022-04-04 14:36:51
 o Last duration        0.92 seconds

#####  Module Start: sensors  #####

 o UEC-STARLINE-MIB     cpmAcInfTotLineCurrDemand [+] cpmAcInfLineCurrDemand [++++]

 o Duration             0.7934s

##### [780] completed discovery modules at 2022-04-04 14:37:27  #####

 o Discovery time       0.7966 seconds

#####  Finished discovery run at 2022-04-04 14:37:27  #####

 o Devices Discovered   1
 o Discovery Time       0.828 secs
 o Memory usage         20MB (peak: 20MB)
 o MySQL Usage          Cell[39/0.018s] Row[112/0.027s] Rows[40/0.018s] Column[1/0s] Update[1/0.003s] Insert[1/0.002s] Delete[1/0.001s]
 o RRDTool Usage

More Examples

Further examples on more complex matching, exclusion and description setting can be found by looking through the existing definitions in includes/definitions/mibs/.


This example shows constructing a description from multiple additional OIDs collected with oid_extra

NAS-MIB::hdDescr.1 = STRING: "HDD1"
NAS-MIB::hdTemperature.1 = STRING: "41 C/105 F"
NAS-MIB::hdStatus.2 = INTEGER: ready(0)
NAS-MIB::hdModel.1 = STRING: "ST6000VN0001-1SF17Z"
NAS-MIB::hdCapacity.1 = STRING: "5.46 TB"
NAS-MIB::hdSmartInfo.1 = STRING: "GOOD"
$config['mibs'][$mib]['sensor'][] = [
  'oid'        => 'hdTemperature',
  'descr'      => '%hdDescr% (%hdModel%, %hdCapacity%)',
  'oid_num'    => '.',
  'class'      => 'temperature',
  'oid_extra'  => [ 'hdDescr', 'hdCapacity', 'hdModel' ],

Adding a Status Entity

Status entities are similar to sensors in that they involve a single OID, but they need a translation table to translate the return value into a usable status. We'll use an example from KohlerGCon-MIB which can be foind in includes/definitions/mibs/

KohlerGCon-MIB::gconStatus.1 = INTEGER: good(1)

We can look at the MIB to see what the possible values for this OID are:

gconStatus OBJECT-TYPE
        ACCESS  read-only
        STATUS  mandatory
        DESCRIPTION     "Generator controller comm status."
::= { gconEntry 3 }

From this we can construct a definition for this status. In this instance the 'type' is specific to the OID, so is named after the OID. In some cases the values may be defined in a separate OBJECT-TYPE that is used by multiple OIDs. In these cases it can be defined once and used in multiple OIDs via the type option.

$config['mibs'][$mib]['status'][] = array(
  'oid'       => 'gconStatus',
  'descr'     => 'Controller communication',
  'measured'  => 'controller',
  'type'      => 'gconStatus');

$type = 'gconStatus';
$config['mibs'][$mib]['states'][$type][0] = array('name' => 'unknown',  'event' => 'exclude');
$config['mibs'][$mib]['states'][$type][1] = array('name' => 'good',     'event' => 'ok');
$config['mibs'][$mib]['states'][$type][2] = array('name' => 'error',    'event' => 'alert');

Possible events are ok warn alert ignore and exclude. The first four events produce states in Observium. The fifth, exclude causes the status to be filtered by the discovery process and not added to Observium..

More Examples


NAS-MIB::hdDescr.1 = STRING: "HDD1"
NAS-MIB::hdStatus.2 = INTEGER: ready(0)
NAS-MIB::hdModel.1 = STRING: "ST6000VN0001-1SF17Z"
NAS-MIB::hdCapacity.1 = STRING: "5.46 TB"
NAS-MIB::hdSmartInfo.1 = STRING: "GOOD"
$config['mibs'][$mib]['status'][] = [
  'oid'        => 'hdStatus',
  'descr'      => '%hdDescr% (%hdModel%, %hdCapacity%)',
  'oid_extra'  => [ 'hdDescr', 'hdCapacity', 'hdModel' ],
  'oid_num'    => '.',
  'type'       => 'nas-mib-hd-state',
  'measured'   => 'storage',

$type = 'nas-mib-hd-state';
$config['mibs'][$mib]['states'][$type][0]  = array('name' => 'ready',   'event' => 'ok');
$config['mibs'][$mib]['states'][$type][-5] = array('name' => 'noDisk',  'event' => 'exclude');
$config['mibs'][$mib]['states'][$type][-6] = array('name' => 'invalid', 'event' => 'alert');
$config['mibs'][$mib]['states'][$type][-9] = array('name' => 'rwError', 'event' => 'alert');
$config['mibs'][$mib]['states'][$type][-4] = array('name' => 'unknown', 'event' => 'ignore');