Files
unpoller_unpoller/pkg/promunifi/README.md
T
Cody LeeandClaude Opus 4.7 dabfeffe66 fix(prometheus): serve scrapes from cached background poll (#1013)
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>
2026-05-11 17:43:44 -05:00

33 lines
1.2 KiB
Markdown

# 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):
```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.