feat(net): Tracing resilience layer (Slice 1, PR 5)#86
Conversation
Outermost ADR-0031 §6 layer: one info span per logical request (method, route, status, ErrorKind, latency, attempts), routed to the ADR-0014 Telemetry plane. Timer-generic latency; query-stripped route; structural secret-safety (reads only method/path/status/kind/clock). Includes Retry per-attempt events + an ambient attempt-count record, under a documented "inner layers emit events, not spans" composition contract. Built concurrently with the CircuitBreaker PR (independent files). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Three-task TDD plan: (1) the Tracing layer + capturing-subscriber test harness + secret-safety test; (2) Retry per-attempt events + ambient attempt-count integration test; (3) ADR-0034 amendment, CHANGELOG, gate, PR. Module named 'trace' to avoid shadowing the tracing crate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
✅ Files skipped from review due to trivial changes (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds a request-scoped ChangesTracing Resilience Layer
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
crates/adapter/net/http/api/src/retry.rs (1)
246-259: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse the stable
kind_labelmapping instead ofDebugforerror_kind.The per-attempt event formats
error_kindwith?e.kind()(Debug), while the siblinghttp.requestspan intrace.rsuses a dedicatedkind_label()function specifically to produce "stable, low-cardinality string labels" for this dimension. That means the same logical field (error_kind) will carry two different value conventions across the two telemetry surfaces for the same request (e.g.Connectionhere vsconnectionon the outer span), undermining the ADR-0014 telemetry plane's consistency and any downstream aggregation/filtering keyed on this field.Since
kind_labelis currently private totrace.rs, reusing it here would require exposing it aspub(crate).♻️ Proposed fix
- Err(e) => tracing::event!( - tracing::Level::DEBUG, - attempt = u64::from(attempt), - error_kind = ?e.kind(), - "http.attempt" - ), + Err(e) => tracing::event!( + tracing::Level::DEBUG, + attempt = u64::from(attempt), + error_kind = crate::trace::kind_label(e.kind()), + "http.attempt" + ),And in
trace.rs:-fn kind_label(kind: ErrorKind) -> &'static str { +pub(crate) fn kind_label(kind: ErrorKind) -> &'static str {Please confirm
ErrorKind'sDebugoutput doesn't carry any per-variant payload data before deciding severity here (if it does, this becomes a secret-safety concern rather than just a consistency one).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/adapter/net/http/api/src/retry.rs` around lines 246 - 259, The per-attempt `http.attempt` event in `retry.rs` is using `?e.kind()` for `error_kind`, which is inconsistent with the stable label convention used by `http.request` in `trace.rs`. Update the `tracing::event!` call in the retry path to use the same `kind_label()` mapping for `ErrorKind`, and make that helper `pub(crate)` in `trace.rs` so both telemetry surfaces emit the same low-cardinality string values. Also verify the `ErrorKind` `Debug` output does not include payload data before changing the representation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/superpowers/specs/2026-07-04-net-http-tracing-layer-design.md`:
- Around line 55-57: The spec still references the module as tracing.rs and pub
mod tracing, but the chosen module name is trace; update the references in the
design doc to trace.rs and pub mod trace; and make the same rename anywhere else
in the spec that still mentions tracing so the follow-up implementation matches
the actual module name.
---
Nitpick comments:
In `@crates/adapter/net/http/api/src/retry.rs`:
- Around line 246-259: The per-attempt `http.attempt` event in `retry.rs` is
using `?e.kind()` for `error_kind`, which is inconsistent with the stable label
convention used by `http.request` in `trace.rs`. Update the `tracing::event!`
call in the retry path to use the same `kind_label()` mapping for `ErrorKind`,
and make that helper `pub(crate)` in `trace.rs` so both telemetry surfaces emit
the same low-cardinality string values. Also verify the `ErrorKind` `Debug`
output does not include payload data before changing the representation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: d1abd15d-9c4f-43ff-bcdd-6c754774cd4e
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock,!**/*.lock
📒 Files selected for processing (9)
CHANGELOG.mdCargo.tomlcrates/adapter/net/http/api/Cargo.tomlcrates/adapter/net/http/api/src/lib.rscrates/adapter/net/http/api/src/retry.rscrates/adapter/net/http/api/src/trace.rsdocs/adr/0034-http-construction-surface-auth-guarded-boot-coverage.mddocs/superpowers/plans/2026-07-04-net-http-tracing-layer.mddocs/superpowers/specs/2026-07-04-net-http-tracing-layer-design.md
Address CodeRabbit review on #86: - retry.rs's `http.attempt` event recorded `error_kind` via `?e.kind()` (Debug, e.g. `Connection`) while trace.rs's `http.request` span uses the stable low-cardinality `kind_label` (e.g. `connection`). Same telemetry field, two conventions — split downstream aggregation on the ADR-0014 plane. Expose `kind_label` as `pub(crate)` and reuse it in retry.rs so both surfaces emit identical values. (ErrorKind is a fieldless enum — no payload, so this was consistency-only, not a secret-safety issue.) - Design spec still referenced `tracing.rs`/`pub mod tracing;`; the shipped module is `trace`. Corrected the three stale references. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts: # CHANGELOG.md # docs/adr/0034-http-construction-surface-auth-guarded-boot-coverage.md
Closes #83
Slice 1 PR 5 of the net-http resilience layers (spec: docs/superpowers/specs/2026-07-04-net-http-tracing-layer-design.md; ADR-0031 §6, ADR-0014). The outermost layer; built concurrently with the CircuitBreaker PR (independent files).
Tracing<S, T>+TracingLayer<T>(net-api::Layer) — oneinfospan per logical request (method, route, status,ErrorKind, latency, attempts), attached to the inner future viatracing::Instrumentso downstream events (incl.Retry's per-attempt) nest under it. Latency vianet-api::Timerdeltas.uri().path()(query dropped), status,ErrorKind, and the clock; never headers, never bodies. Body-transparent (Response<B>untouched).Retryinstrumentation —debugper-attempt/backoff events + an ambientSpan::current().record("attempts", n)(a no-op without aTracingspan). Composition contract:Tracingowns the one span; inner layers emit events, not spans.traceto avoid shadowing thetracingcrate.Adds the
tracingfacade (runtime dep, zero executor) +tracing-subscriber(dev-dep).MockTimer-driven tests with inline service doubles + a capturing subscriber, including the load-bearing secret-safety test.Next: Slice 2 — the
stack()/build()assembly that wires the default layer order.🤖 Generated with Claude Code
Summary by CodeRabbit