Skip to content

fix(librenms-health): report numeric sensors that breach their limits#1329

Open
NavidSassan wants to merge 1 commit into
mainfrom
fix/librenms-health-numeric-sensor-limits
Open

fix(librenms-health): report numeric sensors that breach their limits#1329
NavidSassan wants to merge 1 commit into
mainfrom
fix/librenms-health-numeric-sensor-limits

Conversation

@NavidSassan

Copy link
Copy Markdown
Member

Problem

librenms-health derived each sensor's state solely from LibreNMS' state_generic_value, which LibreNMS populates only for discrete state-class sensors (fan ok/fail, psu present/absent, ...). For numeric sensors (temperature, humidity, voltage, power, ...) that column is NULL, so the plugin forced them to OK and every over- or under-limit reading was silently reported as OK. A humidity sensor reading 71.7 with a high limit of 70 showed [OK] while LibreNMS itself flagged it critical.

This is not a regression: numeric-limit alerting was never implemented (the pre-2024 API version never set a state at all).

Fix

Mirror LibreNMS' own Sensor::currentStatus() so the check agrees with the severity shown on the LibreNMS device health pages:

  • CRITICAL at or beyond the hard sensor_limit / sensor_limit_low
  • WARNING at or beyond the soft sensor_limit_warn / sensor_limit_low_warn
  • UNKNOWN for a state sensor without a translation, or a numeric sensor without a reading
  • comparisons are inclusive (>= / <=), matching LibreNMS

The decision lives in a pure get_sensor_state() helper, computed before the row values are turned into display strings.

Output

The value column now shows both limit ranges as low_warn..high_warn/low_crit..high_crit (header Val (warn/crit Range)). An unset range renders as - so the remaining one stays unambiguous — LibreNMS auto-discovery commonly configures only the critical limits, so many sensors legitimately show only a critical range:

Hostname     ! SysName  ! Sensor                   ! Val (warn/crit Range)        ! State
-------------+----------+--------------------------+------------------------------+-----------
192.0.2.11   ! pdu-a1   ! lgpEnvSupplyAirHumidity  ! 71.7 (35.0..65.0/30.0..70.0) ! [CRITICAL]
192.0.2.11   ! pdu-a1   ! lgpEnvReturnAirHumidity  ! 82.0 (-/20.0..70.0)          ! [CRITICAL]
storinator02 ! synoRZ04 ! Disk 17 MZILT1T9HAJQ/007 ! NotInitialized               ! [WARNING]

Tests

Adds a --test seam plus a 15-case unit-test suite (JSON row fixtures, no live database) covering the warn/crit low and high bands, inclusive boundaries, single-sided limits, the - placeholder, state sensors, missing readings, mixed batches and --always-ok.

Also

  • Drops three dead HTTP-era DEFAULT_* constants and the unused lib.librenms import.
  • README updated (states, value-column explanation, and a note that warn limits are often unset by default but can be set per sensor in LibreNMS on the device Health tab).

The plugin derived a sensor's state only from LibreNMS' state_generic_value,
which is populated exclusively for discrete state-class sensors. For numeric
sensors (temperature, humidity, voltage, power, ...) that column is NULL, so
every over- or under-limit reading was silently reported as OK.

Mirror LibreNMS' own Sensor::currentStatus() so the check agrees with the
severity shown on the LibreNMS device health pages: CRITICAL at or beyond the
hard sensor_limit / sensor_limit_low, WARNING at or beyond the soft
sensor_limit_warn / sensor_limit_low_warn (inclusive comparison), UNKNOWN for a
state sensor without a translation or a numeric sensor without a reading. The
decision is extracted into a pure get_sensor_state() helper computed before the
row values are turned into display strings.

The value column now shows both limit ranges as
"low_warn..high_warn/low_crit..high_crit" (header "Val (warn/crit Range)"); an
unset range is shown as "-" so the remaining one stays unambiguous, since
LibreNMS auto-discovery commonly configures only the critical limits.

Add a --test seam plus a unit-test suite (15 cases) covering the warn/crit low
and high bands, inclusive boundaries, single-sided limits, the "-" placeholder,
state sensors, missing readings, mixed batches and --always-ok, driven by JSON
row fixtures without a live database.

Also drop three dead HTTP-era DEFAULT_* constants and the unused lib.librenms
import.
@NavidSassan NavidSassan requested a review from markuslf July 3, 2026 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant