Adds a new `unas` input plugin that polls UNAS Pro storage consoles and
exports console health, storage pools, disks and shares to Prometheus,
InfluxDB and DataDog.
UNAS is a separate plugin rather than a device type inside inputunifi
because a storage-only console has no Network application: it cannot
answer /status, has no sites, and shares none of the UniFi device schema.
The plugin is opt-in and inert until an operator names a console. Opt-in
is expressed as "no devices configured" rather than a `disable` flag,
because a bool named `disable` zero-values to false and so cannot make a
plugin default-off. Initialize returns silently on an empty device list
and, unlike inputunifi, nothing synthesizes a default URL.
Two behaviours are worth calling out for reviewers:
- Metrics returns (metrics, nil) whenever any console was collected.
poller.collectMetrics uses `if err != nil {} else if metric != nil`,
so returning both would discard every healthy console because one
failed. Only a total failure returns an error.
- Re-auth fires on total failure, not on a 401. A mid-session 401 from
GetData surfaces as ErrInvalidStatusCode, not ErrAuthenticationFailed,
so there is no sentinel to match on. Session expiry fails all four
endpoints at once, which is exactly the total-failure case.
Prometheus metrics use the `unifi_unas_` prefix, which diverges from the
`unas_` prefix used by the reference implementation; dashboards built
against that will need query edits.
Requires unifi/v5 v5.31.0 for the UNAS client and structs.
Credit to alexgreenbank/unaspoller for mapping the endpoints.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
prometheus
This package provides the interface to turn UniFi measurements into prometheus exported metrics. Requires the poller package for actual UniFi data collection.
Scrape cache
Prometheus scrapes are served from an in-memory cache refreshed by a background
poller on a fixed interval. This decouples the scrape cadence from the UniFi
API call cadence: scrapes always return immediately, and upstream backpressure
(e.g. 429 Too Many Requests) no longer stalls /metrics.
Config (TOML):
[prometheus]
http_listen = "0.0.0.0:9130"
# How often the background poller refreshes the cache served to /metrics.
# Default: 60s. Values below 15s are clamped to 15s.
interval = "60s"
Environment variable: UP_PROMETHEUS_INTERVAL=60s.
On poll error the last successful snapshot is preserved, so a transient 429 no
longer empties /metrics. To monitor cache staleness, scrape the
unpoller_prometheus_cache_age_seconds gauge — it reports seconds since the
last successful background refresh, or -1 if no refresh has succeeded yet.
The /scrape endpoint (per-target dynamic scrapes) still fetches live but
coalesces concurrent requests for the same target via singleflight, so a
noisy scraper cannot multiply upstream load.