2017-06-26 23:27:57 +01:00
#### Sensors
2019-06-20 13:53:45 -05:00
This document will guide you through adding health / sensor
information for your new device.
2022-11-04 20:22:50 -05:00
Currently, we have support for the following health metrics along with
2019-06-20 13:53:45 -05:00
the values we expect to see the data in:
2017-04-25 18:35:42 +01:00
| Class | Measurement |
| ------------------------------- | --------------------------- |
| airflow | cfm |
2018-05-02 12:34:13 -07:00
| ber | ratio |
2017-04-25 18:35:42 +01:00
| charge | % |
2020-02-25 18:28:04 +01:00
| chromatic_dispersion | ps/nm |
2017-09-29 21:13:27 +01:00
| cooling | W |
2019-01-20 19:24:11 +01:00
| count | # |
2017-04-25 18:35:42 +01:00
| current | A |
| dbm | dBm |
2018-05-02 12:34:13 -07:00
| delay | s |
| eer | eer |
2017-04-25 18:35:42 +01:00
| fanspeed | rpm |
| frequency | Hz |
| humidity | % |
| load | % |
2020-05-31 01:24:43 +02:00
| loss | % |
2017-04-25 18:35:42 +01:00
| power | W |
2019-01-20 19:24:11 +01:00
| power_consumed | kWh |
| power_factor | ratio |
2017-09-29 21:13:27 +01:00
| pressure | kPa |
2018-05-02 12:34:13 -07:00
| quality_factor | dB |
2017-04-25 18:35:42 +01:00
| runtime | Min |
| signal | dBm |
2017-06-26 23:27:57 +01:00
| snr | SNR |
2017-04-25 18:35:42 +01:00
| state | # |
| temperature | C |
2021-01-03 23:35:32 +02:00
| tv_signal | dBmV |
2022-01-08 18:17:08 +01:00
| bitrate | bps |
2017-04-25 18:35:42 +01:00
| voltage | V |
2018-01-18 21:50:19 +01:00
| waterflow | l/m |
2020-10-20 17:11:12 -07:00
| percent | % |
2017-04-25 18:35:42 +01:00
2017-06-26 23:27:57 +01:00
#### Simple health discovery
2019-06-20 13:53:45 -05:00
We have support for defining health / sensor discovery using YAML
files so that you don't need to know how to write PHP.
2017-06-26 23:27:57 +01:00
2019-06-20 13:53:45 -05:00
> Please note that DISPLAY-HINTS are disabled so ensure you use the
> correct divisor / multiplier if applicable.
2017-07-22 15:03:11 +01:00
2019-06-20 13:53:45 -05:00
All yaml files are located in
`includes/definitions/discovery/$os.yaml` . Defining the information
here is not always possible and is heavily reliant on vendors being
2022-11-04 20:22:50 -05:00
sensible with the MIBs they generate. Only snmp walks are supported,
2019-06-20 13:53:45 -05:00
and you must provide a sane table that can be traversed and contains
2022-11-04 20:22:50 -05:00
all the data you need. We will use netbotz as an example here.
2017-06-26 23:27:57 +01:00
`includes/definitions/discovery/netbotz.yaml`
```yaml
mib: NETBOTZV2-MIB
modules:
sensors:
airflow:
2017-07-10 22:27:46 +01:00
options:
2020-09-12 16:26:20 -05:00
skip_value_lt: 0
2017-07-10 22:27:46 +01:00
data:
-
oid: airFlowSensorTable
value: airFlowSensorValue
divisor: 10
2018-11-10 17:45:24 -06:00
num_oid: '.1.3.6.1.4.1.5528.100.4.1.5.1.2.{{ $index }}'
2019-03-05 04:17:14 +01:00
descr: '{{ $airFlowSensorLabel }}'
2017-07-10 22:27:46 +01:00
index: 'airFlowSensorValue.{{ $index }}'
2017-06-26 23:27:57 +01:00
```
At the top you can define one or more mibs to be used in the lookup of data:
`mib: NETBOTZV2-MIB`
2020-03-24 10:13:04 -04:00
For use of multiple MIB files separate them with a colon: `mib: NETBOTZV2-MIB:SECOND-MIB`
2017-06-26 23:27:57 +01:00
2017-07-10 22:27:46 +01:00
For `data:` you have the following options:
2020-02-25 18:28:04 +01:00
The only sensor we have defined here is airflow. The available options
are as follows:
2017-06-26 23:27:57 +01:00
2021-05-05 10:27:10 -05:00
- `oid` (required): This is the name of the table you want to snmp walk for data.
2019-06-20 13:53:45 -05:00
- `value` (optional): This is the key within the table that contains
2021-05-05 10:27:10 -05:00
the value. If not provided will use `oid`
2021-04-22 21:40:45 +02:00
- `num_oid` (required for PullRequests): If not provided, this parameter should be computed
automatically by discovery process. This parameter is still required to
submit a pull request. This is the numerical OID that contains
2021-03-01 16:54:29 +01:00
`value` . This should usually include `{{ $index }}` .
2024-06-13 17:00:03 +02:00
In case the index is a string, `{{ $str_index_as_numeric }}` can be used instead and will convert
the string to the equivalent OID representation.
2019-06-20 13:53:45 -05:00
- `divisor` (optional): This is the divisor to use against the returned `value` .
- `multiplier` (optional): This is the multiplier to use against the returned `value` .
- `low_limit` (optional): This is the critical low threshold that
`value` should be (used in alerting). If an OID is specified then
divisor / multiplier are used.
- `low_warn_limit` (optional): This is the warning low threshold that
`value` should be (used in alerting). If an OID is specified then
divisor / multiplier are used.
- `warn_limit` (optional): This is the warning high threshold that
`value` should be (used in alerting). If an OID is specified then
divisor / multiplier are used.
- `high_limit` (optional): This is the critical high threshold that
`value` should be (used in alerting). If an OID is specified then
divisor / multiplier are used.
- `descr` (required): The visible label for this sensor. It can be a
key with in the table or a static string, optionally using `{{ index }}` .
- `group` (optional): Groups sensors together under in the webui,
displaying this text. Not specifying this will put the sensors in
the default group.
- `index` (optional): This is the index value we use to uniquely
identify this sensor. `{{ $index }}` will be replaced by the `index`
from the snmp walk.
- `skip_values` (optional): This is an array of values we should skip
over (see note below).
- `skip_value_lt` (optional): If sensor value is less than this, skip the discovery.
- `skip_value_gt` (optional): If sensor value is greater than this, skip the discovery.
2024-03-19 10:24:07 +01:00
- `entPhysicalIndex` and `entPhysicalIndex_measured` (optional) : If the
sensor belongs to a physical entity then you can link them here. The currently
supported variants are :
- `entPhysicalIndex` contains the entPhysicalIndex from entPhysical table, and `entPhysicalIndex_measured` is NULL
- `entPhysicalIndex` contains "ifIndex" value of the linked port and `entPhysicalIndex_measured` contains "ports"
2019-06-20 13:53:45 -05:00
- `user_func` (optional): You can provide a function name for the
sensors value to be processed through (i.e. Convert fahrenheit to
celsius use `fahrenheit_to_celsius` )
2022-11-04 20:22:50 -05:00
- `snmp_flags` (optional): this sets the flags to be sent to snmpwalk, it
overrides flags set on the sensor type and os. The default is `'-OQUb'` .
A common issue is dealing with string indexes, setting `'-OQUsbe'` will change them to
numeric oids. Setting `['-OQUsbe', '-Pu']` will also allow _ in oid names. You can find more
in the [Man Page ](https://linux.die.net/man/1/snmpcmd )
2022-10-25 15:31:02 +02:00
- `rrd_type` (optional): You can change the type of the RRD file that will be created to
store the data. By default, type GAUGE is used. More details can be found here:
https://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html
2017-07-10 22:27:46 +01:00
For `options:` you have the following available:
2019-06-20 13:53:45 -05:00
- `divisor` : This is the divisor to use against the returned `value` .
- `multiplier` : This is the multiplier to use against the returned `value` .
- `skip_values` : This is an array of values we should skip over (see note below).
- `skip_value_lt` : If sensor value is less than this, skip the discovery.
- `skip_value_gt` : If sensor value is greater than this, skip the discovery.
2017-06-26 23:27:57 +01:00
2022-11-04 20:22:50 -05:00
Multiple variables can be used in the sensor's definition. The syntax
2019-06-20 13:53:45 -05:00
is `{{ $variable }}` . Any oid in the current table can be used, as
well as pre_cached data. The index ($index) and the sub_indexes (in
case the oid is indexed multiple times) are also available: if
$index="1.20", then $subindex0="1" and $subindex1="20".
2019-03-05 04:17:14 +01:00
2021-04-20 04:26:17 -05:00
When referencing an oid in another table the full index will be used to match the other table.
2021-06-17 03:16:21 +08:00
If this is undesirable, you may use a single sub index by appending the sub index after a colon to
2021-04-20 04:26:17 -05:00
the variable name. Example `{{ $ifName:2 }}`
2019-06-20 13:53:45 -05:00
> `skip_values` can also compare items within the OID table against
2020-02-01 23:28:03 +01:00
> values. The index of the sensor is used to retrieve the value
> from the OID, unless a target index is appended to the OID.
2022-01-26 22:02:57 +00:00
> Additionally, you may check fields from the device.
2020-02-01 23:28:03 +01:00
> Comparisons behave on a logical OR basis when chained, so only
> one of them needs to be matched for that particular sensor
> to be skipped during discovery. An example of this is below:
2017-12-02 22:56:57 +00:00
```yaml
skip_values:
-
oid: sensUnit
op: '!='
value: 4
2020-02-01 23:28:03 +01:00
-
oid: sensConfig.0
op: '!='
value: 1
2022-01-26 22:02:57 +00:00
-
device: hardware
op: 'contains'
value: 'rev2'
2017-12-02 22:56:57 +00:00
```
2021-04-22 21:40:45 +02:00
`op` can be any of the following operators :
2019-07-09 16:47:02 +02:00
> =, !=, ==, !==, <=, >=, <, >,
> starts, ends, contains, regex, in_array, not_starts,
2020-06-14 16:21:22 +02:00
> not_ends, not_contains, not_regex, not_in_array, exists
2021-04-22 21:40:45 +02:00
Example:
2019-07-09 16:47:02 +02:00
```yaml
skip_values:
-
oid: sensorName
op: 'not_in_array'
value: ['sensor1', 'sensor2']
```
2020-06-14 16:21:22 +02:00
```yaml
skip_values:
-
oid: sensorOptionalOID
op: 'exists'
value: false
```
2021-04-22 21:40:45 +02:00
```yaml
temperature:
data:
-
oid: hwOpticalModuleInfoTable
value: hwEntityOpticalTemperature
descr: '{{ $entPhysicalName }}'
index: '{{ $index }}'
skip_values:
-
oid: hwEntityOpticalMode
op: '='
value: '1'
```
2019-06-20 13:53:45 -05:00
If you aren't able to use yaml to perform the sensor discovery, you
will most likely need to use Advanced health discovery.
2017-06-26 23:27:57 +01:00
#### Advanced health discovery
2019-06-20 13:53:45 -05:00
If you can't use the yaml files as above, then you will need to create
2022-11-04 20:22:50 -05:00
the discovery code in php. If it is possible to create via yaml, php discovery
will likely be rejected due to the much higher chance of later problems,
so it is highly suggested to use yaml.
2017-06-26 23:27:57 +01:00
2019-06-20 13:53:45 -05:00
The directory structure for sensor information is
2022-11-04 20:22:50 -05:00
`includes/discovery/sensors/$class/$os.inc.php` . The format of all the
sensors follows the same code format which is to collect sensor information
via SNMP and then call the `discover_sensor()` function; except state
2020-03-03 06:19:23 -06:00
sensors which requires additional code. Sensor information is commonly found in an ENTITY
mib supplied by device's vendor in the form of a table. Other mib tables may be used as
well. Sensor information is first collected by
`includes/discovery/sensors/pre_cache/$os.inc.php` . This program will pull in data
from mib tables into a `$pre_cache` array that can then be used in
`includes/discovery/sensors/$class/$os.inc.php` to extract specific values which are
then passed to `discover_sensor()` .
2017-04-25 18:35:42 +01:00
`discover_sensor()` Accepts the following arguments:
2019-06-20 13:53:45 -05:00
- &$valid = This is always $valid['sensor'], do not pass any other values.
- $class = Required. This is the sensor class from the table above (i.e humidity).
- $device = Required. This is the $device array.
- $oid = Required. This must be the numerical OID for where the data
can be found, i.e .1.2.3.4.5.6.7.0
- $index = Required. This must be unique for this sensor class, device
2022-11-04 20:22:50 -05:00
and type. Typically it's the index from the table being walked, or it
2019-06-20 13:53:45 -05:00
could be the name of the OID if it's a single value.
2022-11-04 20:22:50 -05:00
- $type = Required. This should be the OS name, i.e. pulse.
2019-06-20 13:53:45 -05:00
- $descr = Required. This is a descriptive value for the sensor. Some
devices will provide names to use.
2022-11-04 20:22:50 -05:00
- $divisor = Defaults to 1. This is used to divide the returned value.
2019-06-20 13:53:45 -05:00
- $multiplier = Defaults to 1. This is used to multiply the returned value.
- $low_limit = Defaults to null. Sets the low threshold limit for the
sensor, used in alerting to report out range sensors.
- $low_warn_limit = Defaults to null. Sets the low warning limit for
the sensor, used in alerting to report near out of range sensors.
- $warn_limit = Defaults to null. Sets the high warning limit for the
sensor, used in alerting to report near out of range sensors.
- $high_limit = Defaults to null. Sets the high limit for the sensor,
used in alerting to report out range sensors.
- $current = Defaults to null. Can be used to set the current value on
discovery. Poller will update this on the next poll cycle anyway.
- $poller_type = Defaults to snmp. Things like the unix-agent can set
different values but for the most part this should be left as snmp.
- $entPhysicalIndex = Defaults to null. Sets the entPhysicalIndex to
be used to look up further hardware if available.
- $entPhysicalIndex_measured = Defaults to null. Sets the type of
entPhysicalIndex used, i.e ports.
- $user_func = Defaults to null. You can provide a function name for
the sensors value to be processed through (i.e. Convert fahrenheit
to celsius use `fahrenheit_to_celsius` )
- $group = Defaults to null. Groups sensors together under in the
webui, displaying this text.
2022-10-25 15:31:02 +02:00
- $rrd_type = Default to 'GAUGE'. Allows to change the type of the RRD
file created for this sensor. More details can be found here in the
RRD documentation: https://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html
2019-06-20 13:53:45 -05:00
For the majority of devices, this is all that's required to add
support for a sensor. Polling is done based on the data gathered using
`discover_sensor()` . If custom polling is needed then the file format
is similar to discovery:
`includes/polling/sensors/$class/$os.inc.php` . Whilst it's possible to
perform additional snmp queries within polling this should be avoided
where possible. The value for the OID is already available as `$sensor_value` .
Graphing is performed automatically for sensors, no custom graphing is
required or supported.
Remove guessed limits for some health sensors, documentation for sensor classes (#10327)
* Default to null for group yaml discovery.
* Update test data for a154bda yaml group null fix.
* Changes to guessed limit functions for sensors.
Original behaviour
===================
The file `includes/discovery/functions.inc.php` contains
`sensor_limit_low()` and `sensor_limit()` which both attempt to
guess a sane value for sensors when no explicitly defined
low_limit or high_limit can be found during discovery.
Both switch control structures used in those two functions
have empty case statements which means that if one of those matches,
it's going to fall through and run the code for each subsequent
case until a `break` is reached.
For example, when we call `function sensor_low_limit(dbm, -13.036)`
it will return the value `-12.3842` instead of `null`. That is
because there will be a match at `case 'dbm':` which falls through
all the way to `case 'cooling':`, where it performs
`$limit = -13.036 * 0.95` before hitting a `break`.
Changed behaviour
===================
Removed `power_consumed` and `count` guessed low_limit and
high_limit, I personally added those sensor classes in PR #9471
when I didn't understand that a switch control structure has
fall-through behaviour so I can guarantee that guessing limits for
those is a mistake on my behalf. It should not be there, only
power_factor can have guessed limits. Apologies for the issue,
I'm still a beginning programmer!
Furthermore, I removed guessed high_limit values for `current`
and `power` because these are supposed to draw higher values as
more devices or components are installed on for example a PDU or
a chassis.
Finally, I removed guessed low_limit and high_limit for `dbm`
sensors, there is a much too large variance in power budget on
commercially available optical transceivers for there to be a
sensible window where you can guess these values.
* Documentation on adding sensor classes.
* Update test data - sensor limit changes @ 30212d2
2019-06-21 16:03:27 +02:00
#### Adding a new sensor class
You will need to add code for your new sensor class in the following existing files:
2020-02-25 18:28:04 +01:00
- `app/Models/Sensor.php` : add a free icon from [Font Awesome ](https://fontawesome.com/icons?d=gallery&m=free )
in the $icons array.
2019-10-21 02:47:40 +02:00
- `doc/Developing/os/Health-Information.md` : documentation for every sensor class is mandatory.
- `includes/discovery/sensors.inc.php` : add the sensor class to the $run_sensors array.
2020-02-25 18:28:04 +01:00
- `includes/discovery/functions.inc.php` : optional - if sensible low_limit and high_limit values
are guessable when a SNMP-retrievable threshold is not available, add a case for the sensor class
to the sensor_limit() and/or sensor_low_limit() functions.
2019-10-21 02:47:40 +02:00
- `LibreNMS/Util/ObjectCache.php` : optional - choose menu grouping for the sensor class.
2020-03-03 06:19:23 -06:00
- `includes/html/pages/device/health.inc.php` : add a dbFetchCell(), $datas[], and $type_text[]
entry for the sensor class.
- `includes/html/pages/device/overview.inc.php` : add `require 'overview/sensors/$class.inc.php'`
in the desired order for the device overview page.
- `includes/html/pages/health.inc.php` : add a $type_text[] entry for the sensor class.
2023-04-17 13:51:35 +02:00
- `lang/en/sensors.php` : add human-readable names and units for the sensor class
2020-03-03 06:19:23 -06:00
in English, feel free to do so for other languages as well.
Create and populate new files for the sensor class in the following places:
- `includes/discovery/sensors/$class/` : create the folder where advanced php-based discovery
files are stored. Not used for yaml discovery.
=======
2019-10-21 02:47:40 +02:00
- `includes/html/pages/device/health.inc.php` : add a dbFetchCell(), $datas[], and $type_text[] entry for the sensor class.
2020-02-25 18:28:04 +01:00
- `includes/html/pages/device/overview.inc.php` : add `require 'overview/sensors/$class.inc.php'` in the desired
order for the device overview page.
2019-10-21 02:47:40 +02:00
- `includes/html/pages/health.inc.php` : add a $type_text[] entry for the sensor class.
2023-04-17 13:51:35 +02:00
- `lang/en/sensors.php` : add human-readable names and units for the sensor class in English, feel
2020-02-25 18:28:04 +01:00
free to do so for other languages as well.
Remove guessed limits for some health sensors, documentation for sensor classes (#10327)
* Default to null for group yaml discovery.
* Update test data for a154bda yaml group null fix.
* Changes to guessed limit functions for sensors.
Original behaviour
===================
The file `includes/discovery/functions.inc.php` contains
`sensor_limit_low()` and `sensor_limit()` which both attempt to
guess a sane value for sensors when no explicitly defined
low_limit or high_limit can be found during discovery.
Both switch control structures used in those two functions
have empty case statements which means that if one of those matches,
it's going to fall through and run the code for each subsequent
case until a `break` is reached.
For example, when we call `function sensor_low_limit(dbm, -13.036)`
it will return the value `-12.3842` instead of `null`. That is
because there will be a match at `case 'dbm':` which falls through
all the way to `case 'cooling':`, where it performs
`$limit = -13.036 * 0.95` before hitting a `break`.
Changed behaviour
===================
Removed `power_consumed` and `count` guessed low_limit and
high_limit, I personally added those sensor classes in PR #9471
when I didn't understand that a switch control structure has
fall-through behaviour so I can guarantee that guessing limits for
those is a mistake on my behalf. It should not be there, only
power_factor can have guessed limits. Apologies for the issue,
I'm still a beginning programmer!
Furthermore, I removed guessed high_limit values for `current`
and `power` because these are supposed to draw higher values as
more devices or components are installed on for example a PDU or
a chassis.
Finally, I removed guessed low_limit and high_limit for `dbm`
sensors, there is a much too large variance in power budget on
commercially available optical transceivers for there to be a
sensible window where you can guess these values.
* Documentation on adding sensor classes.
* Update test data - sensor limit changes @ 30212d2
2019-06-21 16:03:27 +02:00
Create and populate new files for the sensor class in the following places:
2020-02-25 18:28:04 +01:00
- `includes/discovery/sensors/$class/` : create the folder where advanced php-based discovery files
are stored. Not used for yaml discovery.
2019-10-21 02:47:40 +02:00
- `includes/html/graphs/device/$class.inc.php` : define unit names used in RRDtool graphs.
- `includes/html/graphs/sensor/$class.inc.php` : define various [parameters ](https://oss.oetiker.ch/rrdtool/doc/rrdgraph_graph.en.html ) for RRDtool graphs.
- `includes/html/pages/device/health/$class.inc.php`
- `includes/html/pages/device/overview/sensors/$class.inc.php`
- `includes/html/pages/health/$class.inc.php`
2020-03-03 06:19:23 -06:00
#### Advanced health sensor example
This example shows how to build sensors using the advanced method. In this example we will
be collecting optical power level (dBm) from Adva FSP150CC family MetroE devices. This example
will assume an understanding of SNMP and MIBs.
First we setup `includes/discovery/sensors/pre_cache/adva_fsp150.inc` as shown below. The first
line walks the cmEntityObject table to get information about the chassis and line cards. From
this information we extract the model type which will identify which tables in the CM-Facility-Mib
the ports are populated in. The program then reads the appropriate table into the `$pre_cache`
array `adva_fsp150_ports` . This array will have OID indexies for each port, which we will use
2021-06-17 03:16:21 +08:00
later to identify our sensor OIDs.
2020-03-03 06:19:23 -06:00
```
$pre_cache['adva_fsp150'] = snmpwalk_cache_multi_oid($device, 'cmEntityObjects', [], 'CM-ENTITY-MIB', null, '-OQUbs');
$neType = $pre_cache['adva_fsp150'][1]['neType'];
if ($neType == 'ccxg116pro') {
$pre_cache['adva_fsp150_ports'] = snmpwalk_cache_multi_oid($device, 'cmEthernetTrafficPortTable', $pre_cache['adva_fsp150_ports'], 'CM-FACILITY-MIB', null, '-OQUbs');
} else {
$pre_cache['adva_fsp150_ports'] = snmpwalk_cache_multi_oid($device, 'cmEthernetNetPortTable', $pre_cache['adva_fsp150_ports'], 'CM-FACILITY-MIB', null, '-OQUbs');
$pre_cache['adva_fsp150_ports'] = snmpwalk_cache_multi_oid($device, 'cmEthernetAccPortTable', $pre_cache['adva_fsp150_ports'], 'CM-FACILITY-MIB', null, '-OQUbs');
}
```
Next we are going to build our sensor discovery code. These are optical readings, so the file will be
created as the dBm sensor type in `includes/discover/sensors/dbm/adva_fsp150.inc.php` . Below is
a snippet of the code:
```
foreach ($pre_cache['adva_fsp150_ports'] as $index => $entry) {
if ($entry['cmEthernetTrafficPortMediaType'] == 'fiber') {
//Discover received power level
$oidRx = '.1.3.6.1.4.1.2544.1.12.5.1.21.1.34.' . $index . '.3';
$oidTx = '.1.3.6.1.4.1.2544.1.12.5.1.21.1.33.' . $index . '.3';
$currentRx = snmp_get($device, $oidRx, '-Oqv', 'CM-PERFORMANCE-MIB', '/opt/librenms/mibs/adva');
$currentTx = snmp_get($device, $oidTx, '-Oqv', 'CM-PERFORMANCE-MIB', '/opt/librenms/mibs/adva');
if ($currentRx != 0 || $currentTx != 0) {
$entPhysicalIndex = $entry['cmEthernetTrafficPortIfIndex'];
$entPhysicalIndex_measured = 'ports';
$descrRx = dbFetchCell('SELECT `ifName` FROM `ports` WHERE `ifIndex` = ? AND `device_id` = ?', [$entry['cmEthernetTrafficPortIfIndex'], $device['device_id']]) . ' Rx Power';
discover_sensor(
$valid['sensor'],
'dbm',
$device,
$oidRx,
'cmEthernetTrafficPortStatsOPR.' . $index,
'adva_fsp150',
$descrRx,
$divisor,
$multiplier,
null,
null,
null,
null,
$currentRx,
'snmp',
$entPhysicalIndex,
$entPhysicalIndex_measured
);
$descrTx = dbFetchCell('SELECT `ifName` FROM `ports` WHERE `ifIndex` = ? AND `device_id` = ?', [$entry['cmEthernetTrafficPortIfIndex'], $device['device_id']]) . ' Tx Power';
discover_sensor(
$valid['sensor'],
'dbm',
$device,
$oidTx,
'cmEthernetTrafficPortStatsOPT.' . $index,
'adva_fsp150',
$descrTx,
$divisor,
$multiplier,
null,
null,
null,
null,
$currentTx,
'snmp',
$entPhysicalIndex,
$entPhysicalIndex_measured
);
}
}
}
```
First the program will loop through each port's index value. In the case of Advas, the ports are
names Ethernet 1-1-1-1, 1-1-1-2, etc, and they are indexed as oid.1.1.1.1, oid.1.1.1.2, etc in
the mib.
Next the program checks which table the port exists in and that the connector type is 'fiber'. There
are other port tables in the full code that were ommitted from the example for brevity. Copper
media won't have optical readings, so if the media type isn't fiber we skip discovery for that port.
The next two lines build the OIDs for getting the optical receive and transmit values using the
`$index` for the port. Using the OIDs the program gets the current receive and transmit values
($currentRx and $currentTx repectively) to verify the values are not 0. Not all SFPs collect digital
optical monitoring (DOM) data, in the case of Adva the value of both transmit and recieve will be
0 if DOM is not available. While 0 is a valid value for optical power, its extremely unlikely that
both will be 0 if DOM is present. If DOM is not available, then the program stops discovery for
that port. Note that while this is the case with Adva, other vendors may differ in how they handle
optics that do not supply DOM. Please check your vendor's mibs.
Next the program assigns the values of $entPhysicalIndex and $entPhysicalIndex_measured. In this
case $entPhysicalIndex is set to the value of the `cmEthernetTrafficPortIfIndex` so that it is
associated with port. This will also allow the sensor graphs to show up on the associated port's
page in the GUI in addition to the Health page.
Following that the program uses a database call to get the description of the port which will be
used as the title for the graph in the GUI.
Lastly the program calls `discover_sensor()` and passes the information collected in the previous
steps. The `null` values are for low, low warning, high, and high warning values, which are not
collected in the Adva's MIB.
You can manually run discovery to verify the code works by running `./discovery.php -h $device_id -m sensors` .
You can use `-v` to see what calls are being used during discovery and `-d` to see debug output.
In the output under `#### Load disco module sensors ####` you can see a list of sensors types. If
there is a `+` a sensor is added, if there is a `-` one was deleted, and a `.` means no change. If
there is nothing next to the sensor type then the sensor was not discovered. There is is also
information about changes to the database and RRD files at the bottom.
```
[librenms@nms -test ~]$ ./discovery.php -h 2 -m sensors
LibreNMS Discovery
164.113.194.250 2 adva_fsp150
#### Load disco module core ####
>> Runtime for discovery module 'core': 0.0240 seconds with 66536 bytes
>> SNMP: [2/0.06s] MySQL: [3/0.00s] RRD: [0/0.00s]
#### Unload disco module core ####
#### Load disco module sensors ####
Pre-cache adva_fsp150:
ENTITY-SENSOR: Caching OIDs: entPhysicalDescr entPhysicalName entPhySensorType entPhySensorScale entPhySensorPrecision entPhySensorValue entPhySensorOperStatus
Airflow:
Current: .
Charge:
Dbm: Adva FSP-150 dBm..
Fanspeed:
Frequency:
Humidity:
Load:
Power:
Power_consumed:
Power_factor:
Runtime:
Signal:
State:
Count:
Temperature: ..
2022-01-08 18:17:08 +01:00
Tv_signal:
Bitrate:
2020-03-03 06:19:23 -06:00
Voltage: .
Snr:
Pressure:
Cooling:
Delay:
Quality_factor:
Chromatic_dispersion:
Ber:
Eer:
Waterflow:
2020-10-20 17:11:12 -07:00
Percent:
2020-03-03 06:19:23 -06:00
>> Runtime for discovery module 'sensors': 3.9340 seconds with 190024 bytes
>> SNMP: [16/3.89s] MySQL: [36/0.03s] RRD: [0/0.00s]
#### Unload disco module sensors ####
Discovered in 5.521 seconds
SNMP [18/3.96s]: Get[8/0.81s] Getnext[0/0.00s] Walk[10/3.15s]
MySQL [41/0.03s]: Cell[10/0.01s] Row[-4/-0.00s] Rows[31/0.02s] Column[0/0.00s] Update[2/0.00s] Insert[2/0.00s] Delete[0/0.00s]
RRD [0/0.00s]: Update[0/0.00s] Create [0/0.00s] Other[0/0.00s]
```