feat(cli): deepen sentry observability -- source maps, tracing, anonymization, crash refs#628
Merged
Conversation
…zation, crash refs) Builds on the crash reporting from #621: - Source maps: emit dist/cli.js.map and upload to Sentry with Debug IDs (scripts/sentry-sourcemaps.mjs, wired into the release + @dev publish jobs) for de-minified stack traces. Maps are uploaded, not shipped in the tarball. - Tracing: each run is a Sentry transaction; the existing Effect spans (runInspect + every Effect.fn service span) are bridged into one unified per-run trace. A user's own OTLP backend still wins and shares the trace_id. - Environment/run info: environment + react-doctor@<version> release, configurable tracesSampleRate, and the run + detected project shape attached as searchable tags/context on every event. - Anonymized telemetry: sendDefaultPii off; hostname/IP/device name and captured local variables stripped; home-dir paths and known secrets scrubbed from all events; identifying projectName/rootDirectory omitted. - Crash references: the Sentry event id is surfaced in the CLI error output and the prefilled GitHub issue, and scan errors are linked back to the run trace. Opt-out and CLI-only: --no-score disables Sentry entirely, it is skipped under tests, and the programmatic @react-doctor/api library never initializes Sentry. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # packages/react-doctor/src/cli/index.ts
commit: |
Contributor
|
React Doctor found 38 files changed in this pull request, but none matched the files covered by its enabled checks. Scope: 38 files changed on Generated by React Doctor. Questions? Contact founders@million.dev. |
Bugbot flagged that the module-level project-info and active-run-trace refs weren't reset per run, so a multi-project workspace scan could attach a prior project's tags (or a stale trace) to a later project's error thrown before its beforeLint hook. Clear both at the start of each inspect() via resetSentryRunState(); add a regression test. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8d3e9ba. Configure here.
Address Bugbot: clearing only the trace on success (not the project ref) left post-scan work in inspectAction (finalize/handoff, or the next workspace project) tagged with a stale project and unlinked. Now inspect() clears BOTH the project ref and the run trace when a scan finishes cleanly, and persists both on a thrown error so the command catch can still attribute and link the crash. withSentryRunSpan only records the trace; inspect() owns the reset. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # packages/react-doctor/README.md
Co-authored-by: Cursor <cursoragent@cursor.com>
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Why
The CLI got crash reporting in #621, but the events that land in Sentry aren't very debuggable: stack frames point at the bundled
dist/cli.js, there's no environment / release / trace context, the run sends PII (sendDefaultPii: true, rawcwd/argv, hostname, IP), and a user who hits a crash has no way to point us at the exact event.This makes the telemetry actually useful for triage while keeping it anonymized and opt-out.
Before (a crash in Sentry today):
After:
What changed
dist/cli.js.mapand upload it to Sentry with Debug IDs (scripts/sentry-sourcemaps.mjs, wired into the release +@devpublish jobs) so frames symbolicate to original TypeScript. Maps are uploaded, not shipped in the npm tarball. No-op without theSENTRY_AUTH_TOKEN/SENTRY_ORG/SENTRY_PROJECTCI secrets.runInspect+ everyEffect.fn("Service.method")span) is bridged into one unified per-run trace. A user's own OTLP backend (REACT_DOCTOR_OTLP_*) still wins and is parented under the Sentry trace so the two share atrace_id.environment, areact-doctor@<version>release, configurabletracesSampleRate, and attaches the run snapshot (command, origin cli/ci/agent, package manager, Node major, …) as searchable tags + context on every event.project.*tags + aprojectcontext block; identifyingprojectName/rootDirectoryare omitted.sendDefaultPii: false;beforeSend/beforeSendTransactionstrip hostname/server_name/device name and captured local variables, and scrub home-dir paths (username →~) and known secrets/emails from all events (reusing core'sredactSensitiveText). Drops the event if scrubbing fails.reportErrorToSentryreturns the Sentry event id; the CLI surfaces it ("Reference (mention this when reporting): …") and embeds it in the prefilled GitHub issue, and scan-time errors are linked back to the run's trace.SENTRY_DSN,SENTRY_ENVIRONMENT,SENTRY_RELEASE,SENTRY_TRACES_SAMPLE_RATE(0disables tracing),SENTRY_DEBUG.minor), and README/AGENTS docs.Opt-out and CLI-only:
--no-scoredisables Sentry entirely, it's skipped under tests, and the programmatic@react-doctor/apilibrary never initializes Sentry.Eval results
RDE not run — this is an observability/infrastructure change to the CLI, not a lint rule, so there are no diagnostics to eval. Verified end-to-end instead by intercepting the real Sentry envelope from the built
dist/cli.js: confirmed symbolicated/anonymized payloads (no$HOME, hostname, orserver_name), project attributes on the transaction, and a printed crash reference that matches the capturedevent_id.Test plan
pnpm --filter react-doctor test(focused Sentry suites:scrub-*,sentry-tracer,instrument,report-error,build-sentry-*,with-sentry-run-span,active-run-trace,handle-error,build-run-context,to-span-attributes— 53 passing)pnpm typecheckpnpm lintandpnpm format:checkpnpm buildthen a deliberate throw to eyeball a symbolicated, anonymized Sentry event (and the printed reference)Notes for reviewers
SENTRY_AUTH_TOKEN,SENTRY_ORG,SENTRY_PROJECTfor the source-map upload to run; it no-ops safely without them.Residual risk
--jsonmode the crash reference isn't printed (stdout stays pure JSON); the event is still captured and findable in Sentry by trace/tags.~/.config/git/ignorethat lists.env.local, andCURSOR_AGENT=1); both pass in a clean env / CI.Made with Cursor
Note
Medium Risk
Adds outbound telemetry with path/secret scrubbing and opt-out, but mis-scrubbing or scope leaks would be privacy-sensitive; release/source-map and tracer wiring also touch the published CLI bundle and CI publish path.
Overview
Expands CLI-only Sentry from basic crash dumps into release-aligned, anonymized observability: source maps (bundle
sourcemap: true,scripts/sentry-sourcemaps.mjsonpnpm releaseand@devpublish with Debug IDs; maps not in npm), per-run transactions, and an Effect→Sentry tracer (makeSentryTracer,withSentryRunSpan,applyObservability) so existingrunInspect/Effect.fnspans become one trace. User OTLP (REACT_DOCTOR_OTLP_*) still wins; when both run, Effect traces parent under the Sentry trace for a sharedtrace_id.Privacy and triage:
sendDefaultPii: false,scrubSentryEventonbeforeSend/beforeSendTransaction(drop on scrub failure), path/username scrubbing inbuildRunContext, and anonymousproject.*tags from detectedProjectInfo(no repo name/root). Run metadata is centralized inbuildSentryScopefor every event; scan crashes link viaactive-run-trace+ propagation context.reportErrorToSentryreturns an event id surfaced in stderr and the prefilled GitHub issue;flushSentryruns on the success exit path. Still gated by--no-score/ tests /SENTRY_TRACES_SAMPLE_RATE=0; programmatic API does not init Sentry.Reviewed by Cursor Bugbot for commit 3900472. Bugbot is set up for automated code reviews on this repo. Configure here.