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>
The Site Speed Test poll against the controller's aggregated-dashboard
endpoint has always run unconditionally, so operators whose controllers
misbehave on that endpoint have no way to skip the request. Every other
optional collection already has a save_* flag; this adds the missing one.
Defaults to true in all three default paths (local defaults,
per-controller defaults and remote discovery) so existing setups keep
behaving exactly as before.
Refs #1030
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Decouples Prometheus scrape cadence from upstream UniFi API calls so a
429 backoff loop on the controller side no longer stalls /metrics. The
output plugin now owns a 60s background poller (configurable) whose
result is served from an in-memory cache. Concurrent /scrape requests
for the same target are coalesced via singleflight to prevent a noisy
scraper from multiplying upstream load.
Adds two new metrics so operators can detect cache staleness and
refresh failures independently:
- unpoller_prometheus_cache_age_seconds
- unpoller_prometheus_refresh_failures_total
Background goroutine recovers from panics so a malformed input payload
no longer silently kills refreshes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes#1001. Mirrors the DataDog plugin's global tags feature for
InfluxDB. Per-metric tags take precedence on key collision so
site/device identifiers can never be overwritten by a misconfigured
global. Configurable via TOML/JSON/YAML under influxdb.tags.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds log_unknown_types config option (default: false) to control logging
of unknown UniFi device types. When disabled (default), unknown devices
are silently ignored to reduce log volume. When enabled, they are logged
as DEBUG messages instead of ERROR. Addresses issue #912.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add new save_syslog config option to collect events from the v2 UniFi
system-log API (/v2/api/site/{site}/system-log/all).
Changes:
- Add SaveSyslog field to Controller struct
- Add collectSyslog() function using v2 API
- Keep collectEvents() using v1 API for backwards compatibility
- Add RedactIPPII() helper for PII redaction
- Update lokiunifi to log raw JSON (parseable with Loki | json)
- Reduce indexed labels to low-cardinality fields only
- Add SystemLogEntry handler in lokiunifi report
Config: save_syslog (v2 API) vs save_events (v1 API)
Env: UP_UNIFI_DEFAULT_SAVE_SYSLOG=true