Skip to content

feat(usage): make bucket serving observable [ING-589] - #6295

Open
vincent-pochet wants to merge 1 commit into
feat/usage-bucket-prefetchfrom
feat/ing-589-observability
Open

feat(usage): make bucket serving observable [ING-589]#6295
vincent-pochet wants to merge 1 commit into
feat/usage-bucket-prefetchfrom
feat/ing-589-observability

Conversation

@vincent-pochet

@vincent-pochet vincent-pochet commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #6291, review that one first.

Context

Part of the Realtime Usage project.

The served path delegates to the events store silently by design, so a lagging or broken pipeline
looks exactly like usage merely being slow. Aggregation is the cost, so the win equals coverage:
one delegated high-traffic charge keeps a subscription slow however well the rest is served.

Description

  • Count every current usage lookup as served or delegated, tagged with the reason, from the event store provider — the only place that knows both.
  • Keep the reasons coarse: eight labels an operator would act on differently, rather than one per branch. A failed ClickHouse read shares a label with the callers that decline the prefetch.
  • Report the freshness of the buckets behind a served read, taken as the most recent write: the oldest reports the age of the billing period.
  • Memoize the outcome per (charge, filter), so the cache bypass and the aggregation options count one lookup between them.

Metrics are emitted only for organizations the gate is on for, and none carries an organization,
subscription or charge id. Alert rules and the pipeline's liveness loopback live outside this
repository.

@vincent-pochet
vincent-pochet force-pushed the feat/ing-589-observability branch from 549ea97 to 7d7fa8b Compare September 4, 2026 15:30
## Context

The served path delegates to the events store silently by design, so a lagging or broken
pipeline is indistinguishable from usage merely being slow, which is what usage looked like
before the buckets existed. Aggregation is the cost, so the size of the win equals coverage:
one delegated high-traffic charge keeps a subscription slow however well the rest of the plan
is served.

## Description

Every current usage lookup is now counted as served or delegated and tagged with the reason,
emitted from the event store provider, which is the only place that knows both the decision
and why it was taken. The reasons partition the declines, so a delegation rate can be
explained without reading the code, and the residue left after subtracting the ineligible
charges is the signal that something is wrong.

Alongside it, the freshness of the buckets behind a served read. It is the most recent bucket
write rather than the oldest: the oldest reports the age of the billing period, since a bucket
closed on day one is never rewritten. It cannot tell a stalled pipeline from a charge nobody
sends events for, so liveness stays with the pipeline's own loopback.

The reasons are deliberately coarse. One label per branch would mirror the code rather than
answer a question, and the cases worth separating are the ones an operator would act on
differently. A ClickHouse read that failed is not among them: it already reaches Sentry, so it
shares a label with the callers that decline the prefetch outright.

Metrics are emitted only for organizations the gate is on for, or the disabled buckets would
drown the ratio, and no metric carries an organization, subscription or charge id, so the
series count stays a function of the reason list rather than of the customer base.

The alert rules and the pipeline's own liveness loopback live outside this repository.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vincent-pochet
vincent-pochet force-pushed the feat/ing-589-observability branch from 7d7fa8b to e66f8bd Compare September 4, 2026 15:40
@lago-claude-ai-agent

Copy link
Copy Markdown
Contributor

Automated pre-review (advisory, not a required check) — verdict: PASS · CI green

PASS — The realtime-usage metrics preserve the existing bucket fallback behavior, keep labels bounded, and have focused coverage for delegation reasons, cache outcomes, freshness, coverage, and count regressions.

Non-blocking: the charge-filtered path now returns before the existing alphabetical fee sort; current multi-charge filters share a billable metric, but retaining the sort would avoid a subtle future ordering change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant