feat(selfhost): sampled Sentry spans for review latency - #1904
Conversation
Add a shared Sentry span helper and wire it at the review pipeline's existing trace boundaries so operators can answer "why was this review slow / which stage failed" without digging through logs (JSONbored#1734). Tracing stays strictly opt-in: spans are a complete no-op until SENTRY_TRACES_SAMPLE_RATE is configured above 0 (default 0), independent of error capture. resolveTracesSampleRate clamps the rate to [0,1] and treats a malformed value as off. withSentrySpan runs its callback inside a Sentry span only when sampling is on, tagging it with the safe, low-cardinality attribute subset (secrets/null dropped, strings truncated) — never prompts, diffs, tokens, or bodies. withReviewSpan composes one boundary across BOTH tracers (OpenTelemetry + Sentry), each independently no-op when its backend is off, and replaces the existing withOtelSpan boundaries for the queue-job and AI-provider stages — so a sampled review produces a connected trace (whole-review job span with the AI span nested) where slow or failed stages are filterable. Fully unit-tested (sampling off → no span started; on → named span with safe attributes; error propagation; rate resolution; attribute scrubbing). Documented in .env.example.
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-06-30 22:29:56 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 5 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
JSONbored
left a comment
There was a problem hiding this comment.
This is solid, however, we do need to fix this:
The main maintainability gap is that the new shared wrapper lives in `sentry.ts`, which makes Sentry the owner of a cross-tracer abstraction and will encourage broader modules to import Sentry for non-Sentry concerns.
Closing, resubmit once that's fixed and it should be an easy merge. This is a high priority issue so it deserves a gittensor:priority label when merged.
Summary
Adds sampled Sentry tracing across the review pipeline so operators can answer "why was this review slow?" / "which stage failed?" without digging through scattered logs (#1734). A shared span helper keeps instrumentation consistent and easy to audit; it coexists with the existing OpenTelemetry spans by reusing the same boundaries.
Opt-in & safe by construction
SENTRY_TRACES_SAMPLE_RATE > 0(default0) — independent of error capture.resolveTracesSampleRateclamps to[0,1]and treats a malformed value as off, so a typo can't flood the tracer. With sampling off, no span is started and no trace traffic is emitted.sentrySpanAttributeskeeps only the safe, low-cardinality subset (drops secret-keyed + null, keeps finite numbers/booleans, truncates strings) — never prompts, diffs, review bodies, tokens, headers, or config blobs.What it does
withSentrySpan(name, attributes, fn)— runsfninside a Sentry span (auto-closed, marked errored iffnthrows) when sampling is on; a pure pass-through otherwise.withReviewSpan(name, attributes, fn, options)— the shared wrapper that opens one boundary feeding both tracers (OpenTelemetry + Sentry); each side independently no-ops when its backend is off.Acceptance criteria
fn()).Validation
Node 24, from the repo root:
Unit tests cover: rate resolution (default/clamp/non-finite), attribute scrubbing (secrets/null/NaN/non-scalar dropped, truncation), no-op when off (DSN set, rate 0 → no span), span emission + safe attributes when on,
withReviewSpandriving both tracers, and error propagation. The instrumented call-site lines (selfhost.queue.job,selfhost.ai.provider) are covered by the existing queue/AI suites. Documented in.env.example.Part of #998. Closes #1734