Skip to content

feat(browser): opt-in HTTP failure errors, CSP and browser reports - #1152

Merged
Makisuo merged 3 commits into
feat/browser-sdk-breadcrumbsfrom
feat/browser-sdk-http-errors-csp
Sep 29, 2026
Merged

Makisuo merged 3 commits into
feat/browser-sdk-breadcrumbsfrom
feat/browser-sdk-http-errors-csp

Conversation

@Makisuo

@Makisuo Makisuo commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator

Part 6 of the browser SDK stack. Based on #1151.

What changes

errors.captureHttpStatus (default none)

  • Lists the fetch/XHR response statuses that make a span an error, e.g. [[500, 599], 429].
  • A matching span gets status Error, error.type = the status (HTTP semconv) and error.message = METHOD url-without-query -> status. error_events_mv falls back to error.type/error.message for spans with no exception event, so issues group per endpoint, with ids in the path redacted by the message signature.
  • Applied in the same export-time status policy as the XHR fix in feat(browser): XHR spans and page load timing #1147, so both instrumentations follow one rule. A response status alone is still not an error by default; a network failure always is.
  • We don't just turn on the fetch instrumentation's stable-semconv mode: that marks every status ≥ 400 Error, and every Error span becomes an issue.

CSP and browser reports (reporting.csp default true, reporting.browserReports default false)

  • CSP violations become maple.browser.csp_violation WARN log events (effective directive, blocked URI, disposition, url.full, and the source location as code.file.path / code.line.number / code.column.number).
  • Deprecation and intervention reports become maple.browser.report events.
  • They are logs, not errors, so they never open an issue.
  • A buffered ReportingObserver also delivers reports from before the SDK loaded; the securitypolicyviolation event is the fallback where the observer is missing. Report bodies are parsed into a named shape at the boundary.
  • Each kind of report is sent once per page (a blocked image in a loop is one report), up to 50 kinds.

Reports live in the deferred chunk. First-party eager budget 17 → 17.5 kB for the status ranges in the exporter.

Testing

  • Unit tests for the status policy: ranges and single codes, stable and old-semconv attributes, the failure message, and non-listed statuses still cleared.
  • Browser tests for reports: a real CSP violation delivered through ReportingObserver (meta CSP + blocked image), the DOM-event fallback, once-per-kind dedupe, and turning it off.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

- errors.captureHttpStatus lists the fetch/XHR response statuses that
  make a span an error, e.g. [[500, 599], 429]. Default none: a response
  status alone is not an error, a network failure always is. A matching
  span gets Error, error.type = the status (HTTP semconv) and error.message
  "METHOD url-without-query -> status", so issues group per endpoint with
  ids redacted by the fingerprint. Applied in the same export-time status
  policy as the XHR fix, so both instrumentations follow one rule.
- Content Security Policy violations become maple.browser.csp_violation
  WARN log events (directive, blocked URI, disposition, source location),
  on by default; reporting.browserReports adds deprecation and
  intervention reports as maple.browser.report. Logs, not errors, so they
  never open an issue. Uses a buffered ReportingObserver, which also
  delivers reports from before the SDK loaded, and falls back to the
  securitypolicyviolation event. Each kind is sent once per page, up to 50.
- Reports live in the deferred chunk. First-party eager budget 17 -> 17.5
  kB for the status ranges in the exporter.
@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 58 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 9fa0dc25-0cad-42b5-925b-7f8b55d6bde2

📥 Commits

Reviewing files that changed from the base of the PR and between 6b8ab64 and cad4838.

📒 Files selected for processing (14)
  • docs/browser-sdk.md
  • packages/browser/README.md
  • packages/browser/scripts/size.ts
  • packages/browser/src/config.ts
  • packages/browser/src/deferred/index.ts
  • packages/browser/src/deferred/reports.browser.test.ts
  • packages/browser/src/deferred/reports.ts
  • packages/browser/src/error-filters.ts
  • packages/browser/src/http-status.test.ts
  • packages/browser/src/http-status.ts
  • packages/browser/src/index.ts
  • packages/browser/src/navigation.test.ts
  • packages/browser/src/tracing.browser.test.ts
  • packages/browser/src/tracing.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@maple-review-bot

maple-review-bot Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Maple review

Confidence 5/5 · safe to merge
Add-only, opt-in config with defaults matching the docs; the one thing I could not verify offline is that the XHR instrumentation emits a numeric status attribute for the new range check.
quality 100/100 · no findings · tests covered · risk low · 2/2 new units observable

Adds an opt-in errors.captureHttpStatus policy to HttpStatusExporter, and a deferred startReports module that turns CSP violations and browser deprecation/intervention reports into WARN log events. Self-contained and safe to merge.

  • HttpStatusExporter.apply marks a client span Error when its status matches errors.captureHttpStatus
  • startReports emits maple.browser.csp_violation and maple.browser.report once per kind
  • resolveConfig adds reportCsp (true) and reportBrowser (false)
What was checked
  • error.message grouping claim holds: error_events_mv falls back to error.type/error.message only when StatusMessage is empty (packages/domain/src/tinybird/fingerprint.ts:16), and the export…
  • Non-listed statuses still clear: inRanges over an empty or non-matching list falls through to the existing isStatusOnlyError branch (http-status.ts:74)
  • Report emission path: emitLog queues until the deferred sink attaches and is gated on consent (packages/browser/src/logs.ts:39), so reports cannot leak before consent
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
HttpStatusExporter.apply span post-processing on export span post-processing yes Sets Error status, error.type and error.message on the span itself (http-status.ts:72)
startReports CSP / browser-report listeners browser event handler yes Emits structured WARN log events with maple.csp.* attributes through emitLog (reports.ts:74, reports.ts:93)

8955f21 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple to ask about one.

@maple-review-bot

maple-review-bot Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Maple review

Confidence 5/5 · safe to merge
The status policy is a small, pure wrapper with unit tests for both ranges and non-listed statuses, and the report path degrades to the DOM listener when ReportingObserver is absent.
quality 100/100 · no findings · tests covered · risk low

Adds opt-in errors.captureHttpStatus status ranges to the export-time status policy, plus CSP and deprecation/intervention reports as WARN log events behind reporting.csp / reporting.browserReports. Contained to the browser SDK, tested, and safe to merge.

  • HttpStatusExporter takes captureStatus ranges and marks matching client spans Error with error.type/error.message
  • startReports emits maple.browser.csp_violation and maple.browser.report logs, deduped per kind
  • reporting.csp (default true) and reporting.browserReports (default false) resolve into reportCsp/reportBrowser
What was checked
  • Range matching and the old-semconv fallbacks in statusOf / failureMessage, including a non-listed status still being cleared (http-status.ts:72)
  • Report bodies are parsed defensively via toJSON and malformed field types fall back to undefined (reports.ts:30)
  • URLs emitted in the new log events and the failure message go through scrubUrl or lose their query/fragment (reports.ts:83, http-status.ts:27)

f36aabe · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple to ask about one.

@Makisuo
Makisuo added this pull request to stack #1161 September 29, 2026 21:22
@maple-review-bot

maple-review-bot Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Maple review

Confidence 4/5 · likely safe to merge
The delta since the last review is one stateful-regex fix with a test that fails without it, plus a type-only option already wired end to end.
quality 100/100 · no findings · tests covered · risk medium · 2/2 new units observable

Reviewed the two files changed since the last pass. matches now clears a stateful g/y regex's lastIndex before test, and ErrorFilterOptions.captureHttpStatus is declared as ReadonlyArray<HttpStatusRange> (type-only import) and already reaches HttpStatusExporter. No defect found in the delta.

  • matches resets lastIndex before test, so a g/y pattern cannot skip matches
  • ErrorFilterOptions.captureHttpStatus typed against HttpStatusRange, re-exported from the package root
What was checked
  • error-filters.test.ts:83 uses /chunk/gi three times, so it fails if the reset is removed
  • import type at error-filters.ts:4 keeps the http-status import type-only, no runtime cycle
  • captureHttpStatus flows config.ts:242 → tracing.ts:175 into HttpStatusExporter
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
HttpStatusExporter HTTP status error policy (error.type/error.message on listed statuses) in-process span exporter yes The exporter decides the span's own status and error attributes, which is the telemetry itself; covered by http-status.test.ts
ReportingObserver / securitypolicyviolation listener in deferred/reports.ts inbound browser event consumer yes Emits maple.browser.csp_violation and maple.browser.report OTLP log events via emitLog, matching the SDK's log-event convention (web vitals)

cad4838 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple to ask about one.

@Makisuo
Makisuo merged commit 6f80406 into main Sep 29, 2026
37 checks passed
@Makisuo
Makisuo deleted the feat/browser-sdk-http-errors-csp branch September 29, 2026 21:44
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