mirror of
https://github.com/unpoller/unpoller.git
synced 2026-10-18 04:35:53 +02:00
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>
33 lines
1.2 KiB
Markdown
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.
|