diff --git a/package.json b/package.json index f1446c2f49..1dbcf5ea91 100644 --- a/package.json +++ b/package.json @@ -138,6 +138,7 @@ "@react-navigation/bottom-tabs": "^7.15.5", "@react-navigation/native": "^7.1.33", "@react-navigation/native-stack": "^7.14.4", + "@sentry/browser": "10.64.0", "@sentry/react-native": "~8.18.0", "@tanstack/query-async-storage-persister": "^5.96.2", "@tanstack/react-query": "^5.96.2", diff --git a/src/logger/sentry/lib/index.web.ts b/src/logger/sentry/lib/index.web.ts new file mode 100644 index 0000000000..af3d974dd8 --- /dev/null +++ b/src/logger/sentry/lib/index.web.ts @@ -0,0 +1,39 @@ +import { + addBreadcrumb, + captureException, + captureFeedback, + captureMessage, + getClient, + startInactiveSpan, + withActiveSpan, + withScope, +} from '@sentry/browser' + +/** + * Web counterpart of ./index.ts. Importing from `@sentry/browser` instead of + * `@sentry/react-native` keeps the RN SDK layer (native wrapper, RN tracing, + * feedback widget, RN integrations - roughly 200KB minified) out of the web + * bundle. All of these APIs are re-exported from `@sentry/core` by both + * packages, so behavior is identical. + * + * When the app needs another SDK function, add it here and to ./index.ts, then + * run a web build to confirm the bundle size is unaffected. + */ +export const Sentry = { + addBreadcrumb, + captureException, + captureFeedback, + captureMessage, + getClient, + startInactiveSpan, + withActiveSpan, + withScope, + /** + * `wrap` does not exist in `@sentry/browser`. On web, the RN SDK's `wrap` + * only adds a touch-event breadcrumb boundary and a React profiler span, so + * we pass the root component through unchanged. + */ + wrap:

>( + component: React.ComponentType

, + ): React.ComponentType

=> component, +} diff --git a/src/logger/sentry/setup/index.web.ts b/src/logger/sentry/setup/index.web.ts new file mode 100644 index 0000000000..a927321b0d --- /dev/null +++ b/src/logger/sentry/setup/index.web.ts @@ -0,0 +1,51 @@ +import {init} from '@sentry/browser' + +import * as env from '#/env' + +/* + * Web counterpart of ./index.ts. Initializing `@sentry/browser` directly + * instead of `@sentry/react-native` keeps the RN SDK layer (native wrapper, + * RN tracing, feedback widget, RN integrations - roughly 200KB minified) out + * of the web bundle. Options mirror the native setup; RN-only options are + * omitted. + */ +init({ + enabled: !env.IS_DEV && !!env.SENTRY_DSN, + dsn: env.SENTRY_DSN, + debug: false, // If `true`, Sentry will try to print out useful debugging information if something goes wrong with sending the event. Set it to `false` in production + environment: env.ENV, + dist: env.BUNDLE_IDENTIFIER, + release: env.RELEASE_VERSION, + ignoreErrors: [ + /* + * Unknown internals errors + */ + `t is not defined`, + `Can't find variable: t`, + /* + * Un-useful errors + */ + `Network request failed`, + ], + /** + * Does not affect traces of error events or other logs, just disables + * automatically attaching stack traces to events. This helps us group events + * and prevents explosions of separate issues. + * + * @see https://docs.sentry.io/platforms/react-native/configuration/options/#attach-stacktrace + */ + attachStacktrace: false, + sampleRate: env.IS_INTERNAL ? 1.0 : 0.1, + /** + * Sample rate for performance spans (video playback, video upload). Setting + * this also enables the SDK's default stall and slow/frozen frame tracking, + * whose measurements attach to every root span. + */ + tracesSampleRate: env.IS_INTERNAL ? 1.0 : 0.01, + /* + * The native setup passes `enableAutoSessionTracking: false`. The browser + * SDK's equivalent is the BrowserSession default integration, so filter it + * out to match. + */ + integrations: defaults => defaults.filter(i => i.name !== 'BrowserSession'), +})