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>
1.2 KiB
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.