Skip to content

Count retries, recoveries and exhausted retries per client - #2930

Merged
MarcusSorealheis merged 2 commits into
TraceMachina:mainfrom
corcillo:corcillo-retry-outcome-metrics
Oct 14, 2026
Merged

MarcusSorealheis merged 2 commits into
TraceMachina:mainfrom
corcillo:corcillo-retry-outcome-metrics

Conversation

@corcillo

Copy link
Copy Markdown
Collaborator

What and why

Cloud stores and gRPC clients retry through Retrier, and they do it silently. When retries run out the operation fails with the last error and nothing is logged. So an incident caused by a throttled backend, such as a cloud storage account at its egress limit, shows up only as failed actions, and whether retries were attempted, and how long they held out, has to be reconstructed from sampled logs.

Retrier now records retry.outcomes{retry.client, retry.outcome}:

  • retried: an attempt failed with a retryable error and another attempt follows
  • recovered: the operation succeeded after at least one retry
  • exhausted: the retries ran out on a retryable error
  • permanent: an error that is never retried. NotFound is left out, since on a store it is the ordinary cache miss.

Each retrier names what it retries for, through a new Retrier::with_client: azure, s3, s3_http, gcs, ontap_s3, grpc_store, grpc_scheduler and connection. Running out of retries now also logs a warning naming the client and the attempt count.

How was this verified?

Not yet compiled or run locally: the Nix dev shell could not download the toolchain on a flaky network, so CI will be the first build. The code is formatted with the repository's nightly rustfmt (2026-08-26).

Tests added in retry_test.rs, using a new Retrier::with_outcome_fn hook, since the tests cannot read the OTel meter:

  • two retryable failures then success report Retried, Retried, Recovered; success on the first attempt reports nothing
  • retryable failures past max_retries report each retry, then Exhausted
  • a non-retryable error reports Permanent; NotFound reports nothing

The existing retry tests are unchanged and should pass as they are: Retrier::new keeps its signature, and the client label defaults to unknown.

The metrics reference is regenerated (gen:metrics-reference). Its header moves from v1.7.2 to v1.7.6, so the diff also picks up instruments added since v1.7.2 that the page had not listed.

Risk

Low. One counter increment per retry event, on paths that are already failing and sleeping. Label cardinality is eight clients times four outcomes.

The only behavior change is the new Retries exhausted warning: a backend that keeps failing produces one warning per operation that runs out of retries, where before it produced none.

AI assistance

I iterated on a prompt, prompted an agent, and did several iterations of review on resulting code.

A store or gRPC client that retries does it silently. When the retries
run out the operation fails with the last error and nothing is logged, so
an incident caused by a throttled backend (an Azure storage account at its
egress limit, say) shows up only as failed actions, and how long the
retries held out has to be reconstructed from sampled logs.

Retrier now records retry.outcomes{retry.client, retry.outcome}:

- retried: an attempt failed with a retryable error and another follows
- recovered: the operation succeeded after at least one retry
- exhausted: the retries ran out on a retryable error
- permanent: an error that is never retried; NotFound is left out, since
  on a store it is the ordinary miss

Each retrier is labeled with what it retries for: azure, s3, s3_http,
gcs, ontap_s3, grpc_store, grpc_scheduler and connection. Running out of
retries now also logs a warning naming the client and the attempt.
@vercel

vercel Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
nativelink Ready Ready Preview Oct 14, 2026 12:13am UTC
nativelink-aidm Ready Ready Preview Oct 14, 2026 12:13am UTC

Request Review

Resolve conflicts with Retry-After support (TraceMachina#2931): the retrier keeps
both its client label and outcome hook and the throttle budget, and
Azure sets both. A throttle waited out within the budget reports
`retried`, and a success after one reports `recovered`, though it spends
no attempt. Regenerate the metrics reference.

@deus-ex-b7r6 deus-ex-b7r6 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@MarcusSorealheis
MarcusSorealheis merged commit 9ff16ea into TraceMachina:main Oct 14, 2026
43 of 68 checks passed

This branch was successfully deployed

2 active deployments
Preview – nativelink — 9b73646e Deployed Oct 14, 2026 by vercel[bot]
Preview – nativelink-aidm — 9b73646e Deployed Oct 14, 2026 by vercel[bot]
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.

3 participants