Files
supabase/packages/common/sentry.ts
Jordi Enric 8984305b1e feat: sample non-crash sentry errors at one percent (#50339)
## Problem

Browser Sentry reporting sends ordinary application errors at full
volume even though full-page crashes are the highest-priority signal.

## Fix

Sample eligible browser errors without `globalErrorBoundary` at 1%
across Studio, www, and docs. Keep 100% of eligible errors tagged with
`globalErrorBoundary`, preserve consent and existing noise filters, and
record the applied rate in `codeSampleRate`.

## How to test

- Run `node node_modules/vitest/vitest.mjs run
../../packages/common/sentry.test.ts lib/sentry-capture.test.tsx` from
`apps/www`.
- Run `node node_modules/vitest/vitest.mjs run
lib/sentry-client-options.test.ts` from `apps/studio`.
- Expected result: tagged page crashes bypass sampling, ordinary errors
use the 1% cutoff, and Studio applies sampling once while preserving its
existing filters.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Bug Fixes**
- Improved error reporting reliability by ensuring page-crash errors are
captured without sampling.
- Non-crash application errors are now sampled at a low rate, with
sampling metadata retained for monitoring.
- Updated filtering behavior so relevant Studio errors continue to be
reported consistently, including errors previously affected by
client-side filtering.
- Preserved filtering for third-party-only errors that do not represent
application failures.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 11:43:24 +02:00

35 lines
1.1 KiB
TypeScript

type SentryEventTags = {
tags?: {
globalErrorBoundary?: string | number | boolean | null
third_party_code?: string | number | boolean | null
codeSampleRate?: string | number | boolean | null
}
}
const NON_CRASH_ERROR_SAMPLE_RATE = 0.01
export function isSentryErrorBoundaryCrash(event: SentryEventTags): boolean {
return event.tags?.globalErrorBoundary === true || event.tags?.globalErrorBoundary === 'true'
}
export function filterSentryEvent<T extends SentryEventTags>(
event: T,
{ isPlatform, hasConsent }: { isPlatform: boolean; hasConsent: boolean }
): T | null {
if (!isPlatform || !hasConsent) return null
const isErrorBoundaryCrash = isSentryErrorBoundaryCrash(event)
const isThirdPartyOnly =
event.tags?.third_party_code === true || event.tags?.third_party_code === 'true'
if (isThirdPartyOnly && !isErrorBoundaryCrash) return null
if (!isErrorBoundaryCrash && Math.random() >= NON_CRASH_ERROR_SAMPLE_RATE) return null
event.tags = {
...event.tags,
codeSampleRate: isErrorBoundaryCrash ? '1' : NON_CRASH_ERROR_SAMPLE_RATE.toString(),
}
return event
}