Skip to content

observability: readiness gauges for runtime ephemeris push / config apply (alert on permanent, non-requeuing failures) #216

Description

@thc1006

Summary

Add a readiness gauge so a permanent, non-requeuing ephemeris-push failure is alertable. PR #215 fixed ntn_operators_ephemeris_push_errors_total to count every push failure (not once per episode), which restores the NTNEphemerisPushFailing alert for transient outages that tight-requeue every minute. But the four permanent reasons that deliberately do not requeue still increment the counter only once, and a rate/increase() alert cannot sustain on a one-shot sample.

Background

pushEphemerisUpdateIfNeeded classifies failures via ephemerisPushShouldRequeue(reason):

  • Requeuing (transient) — e.g. ProviderPushFailed, gNB unreachable, API GET error → RequeueAfter: 1m. The per-failure counter (shipped in feat(controller): WO-20 event & GitOps hygiene — emit after status, gate on transition #215) advances each minute, so increase(ntn_operators_ephemeris_push_errors_total[15m]) > 0 for: 15m fires and stays firing through the outage. ✅ Covered.
  • Non-requeuing (permanent)EphemerisRefNotFound, EphemerisPayloadMissing, EphemerisStale, ProviderPushRejected. These clear only on an external change (spec edit / ephemeris refresh), so the reconcile does not retry. The counter increments once; increase(...[15m]) is true for ~15m then resolves, so a persistent misconfiguration goes unalerted. ❌ Not covered by a rate alert.

The durable EphemerisPushed=False condition already records the permanent failure for kubectl inspection, but there is no alertable metric for it. A misconfiguration that silently prevents ephemeris push is arguably more important to alert on than a transient blip (which often self-heals).

Proposal

Add a readiness gauge:

ntn_operators_ephemeris_push_ready{namespace, config}  0|1
  • 1 on a successful push (or when the push is already up to date / not configured — "not currently failing").
  • 0 on any push failure, regardless of reason.
  • DeletePartialMatch{namespace, config} on finalizer cleanup (mirrors the counter, prevents cardinality leak on CR delete).

Alert:

- alert: NTNEphemerisPushNotReady
  expr: ntn_operators_ephemeris_push_ready == 0
  for: 15m

A gauge value persists in the TSDB between scrapes, so == 0 for 15m fires even when the reconcile does not requeue — covering the permanent reasons that the counter alert cannot. It is complementary to, not a replacement for, the existing NTNEphemerisPushFailing counter-rate alert (which measures failure rate during a churning transient outage).

Scope decision (design, before code)

Do this holistically, not as a one-metric bolt-on:

  • Apply the same readiness pattern to ConfigApplyErrorsTotal (ntn_operators_config_apply_ready) so runtime push and config apply are consistent, rather than leaving an asymmetry (push has readiness, apply does not).
  • Keep the existing *_errors_total counters and their rate alerts (failure rate ≠ currently-broken); the gauges add the "currently broken" signal.
  • Update dist/chart/templates/monitoring/prometheusrule.yaml, the docs/runbooks/alerts.md runbook, and optionally the Grafana dashboard.
  • Tests: gauge → 0 on failure, → 1 on success/recovery/up-to-date, deleted on CR delete; and that the readiness alert expression behaves for a non-requeuing reason.

Origin

Surfaced in the PR #215 (WO-20) adversarial review. The minimal per-failure counter fix shipped in #215; this gauge is the tracked follow-up for the permanent-reason coverage the counter fundamentally cannot provide.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions