Epic: Cross-cutting / smaller items
Suggested extra label: ops.
Why
GET /healthz returns a static ok (server.go:76 → handleHealthz); it stays green even if the collector goroutine has stalled and the metrics are stale. systemd / uptime monitors cannot detect that failure mode.
Scope
Optionally report unhealthy (non-200) when the latest snapshot is older than a configurable staleness bound. The snapshot already carries a Timestamp (collector.go:138 Snapshot()), so freshness is now - Snapshot().Timestamp compared against a multiple of the fast poll interval.
Reuse & touch points
internal/httpapi/handlers.go — handleHealthz.
MetricsProvider already exposes Snapshot() (server.go:19).
- Optional config
healthz_max_staleness.
API & config impact
/healthz may now return non-200 (document this); keep it auth-exempt as today (handlers_test.go:160).
Acceptance criteria
- A fake provider with a stale timestamp yields a non-200 response.
- A fresh snapshot yields 200
ok.
Epic: Cross-cutting / smaller items
Suggested extra label:
ops.Why
GET /healthzreturns a staticok(server.go:76→handleHealthz); it stays green even if the collector goroutine has stalled and the metrics are stale. systemd / uptime monitors cannot detect that failure mode.Scope
Optionally report unhealthy (non-200) when the latest snapshot is older than a configurable staleness bound. The snapshot already carries a
Timestamp(collector.go:138Snapshot()), so freshness isnow - Snapshot().Timestampcompared against a multiple of the fast poll interval.Reuse & touch points
internal/httpapi/handlers.go—handleHealthz.MetricsProvideralready exposesSnapshot()(server.go:19).healthz_max_staleness.API & config impact
/healthzmay now return non-200 (document this); keep it auth-exempt as today (handlers_test.go:160).Acceptance criteria
ok.