From dfd609f5efe4692ed1d0e87fac3b57ef8e8fa080 Mon Sep 17 00:00:00 2001 From: Matej Kriz Date: Wed, 9 Apr 2025 17:28:56 +0200 Subject: [PATCH] feat(sentry): filter sentry events by allowReportTag same as on desktop - Allow to report only redacted event before info about user confirmation of analytics is loaded or during initial lunch before we even asked user to allow analytics. --- suite-native/analytics/src/analyticsThunks.ts | 5 ++ suite-native/app/package.json | 2 +- suite-native/app/src/App.tsx | 38 +++++++-------- suite-native/app/src/SentryProvider.tsx | 47 ------------------- suite-native/app/tsconfig.json | 1 + suite-native/sentry/package.json | 4 +- suite-native/sentry/src/sentry.ts | 38 +++++++++++++++ suite-native/sentry/tsconfig.json | 3 +- yarn.lock | 4 +- 9 files changed, 72 insertions(+), 70 deletions(-) delete mode 100644 suite-native/app/src/SentryProvider.tsx diff --git a/suite-native/analytics/src/analyticsThunks.ts b/suite-native/analytics/src/analyticsThunks.ts index 841e6de9f0..b207e97f87 100644 --- a/suite-native/analytics/src/analyticsThunks.ts +++ b/suite-native/analytics/src/analyticsThunks.ts @@ -7,6 +7,7 @@ import { } from '@suite-common/analytics'; import { createThunk } from '@suite-common/redux-utils'; import { isDevelopEnv } from '@suite-native/config'; +import { allowSentryReport, setSentryUser } from '@suite-native/sentry'; import { getTrackingRandomId } from '@trezor/analytics'; import { getCommitHash } from '@trezor/env-utils'; @@ -22,6 +23,7 @@ export const enableAnalyticsThunk = createThunk( type: EventType.SettingsDataPermission, payload: { analyticsPermission: true }, }); + allowSentryReport(true); dispatch(analyticsActions.enableAnalytics()); }, ); @@ -33,6 +35,7 @@ export const disableAnalyticsThunk = createThunk( { type: EventType.SettingsDataPermission, payload: { analyticsPermission: false } }, { force: true }, ); + allowSentryReport(false); dispatch(analyticsActions.disableAnalytics()); }, ); @@ -59,6 +62,8 @@ export const initAnalyticsThunk = createThunk( }, }); + allowSentryReport(!!userAllowedTracking); + dispatch( analyticsActions.initAnalytics({ instanceId, diff --git a/suite-native/app/package.json b/suite-native/app/package.json index 07ad14bac6..adb3f7b24b 100644 --- a/suite-native/app/package.json +++ b/suite-native/app/package.json @@ -31,7 +31,6 @@ "@react-navigation/native": "6.1.18", "@react-navigation/native-stack": "6.11.0", "@reduxjs/toolkit": "2.6.0", - "@sentry/core": "8.55.0", "@sentry/react-native": "6.10.0", "@shopify/flash-list": "1.7.3", "@shopify/react-native-skia": "^1.11.6", @@ -77,6 +76,7 @@ "@suite-native/navigation": "workspace:*", "@suite-native/notifications": "workspace:*", "@suite-native/receive": "workspace:*", + "@suite-native/sentry": "workspace:*", "@suite-native/settings": "workspace:*", "@suite-native/state": "workspace:*", "@suite-native/storage": "workspace:*", diff --git a/suite-native/app/src/App.tsx b/suite-native/app/src/App.tsx index 0d7b623d4d..bf775eb78d 100644 --- a/suite-native/app/src/App.tsx +++ b/suite-native/app/src/App.tsx @@ -13,11 +13,11 @@ import { configureNetInfo } from '@suite-native/connection-status'; import { IntlProvider } from '@suite-native/intl'; import { KillswitchMessageScreen } from '@suite-native/message-system'; import { NavigationContainerWithAnalytics } from '@suite-native/navigation'; +import { initSentry } from '@suite-native/sentry'; import { StoreProvider, selectIsAppReady, selectIsConnectInitialized } from '@suite-native/state'; import { BannersRenderer } from './BannersRenderer'; import { ModalsRenderer } from './ModalsRenderer'; -import { SentryProvider } from './SentryProvider'; import { StylesProvider } from './StylesProvider'; import { useFormattersConfig } from './hooks/useFormattersConfig'; import { useReportAppInitToAnalytics } from './hooks/useReportAppInitToAnalytics'; @@ -25,18 +25,20 @@ import { applicationInit } from './initActions'; import { RootStackNavigator } from './navigation/RootStackNavigator'; import { disableRTL } from './rtl'; -if (__DEV__) { - require('./LogBox'); -} - -// Right-to-left language support is not supported yet. -disableRTL(); - // Base time to measure app loading time. // The constant has to be placed at the beginning of this file to be initialized as soon as possible. // TODO: This method of measuring app loading time is not ideal, Should be substituted by some more sophisticated solution in the future. const APP_STARTED_TIMESTAMP = Date.now(); +if (__DEV__) { + require('./LogBox'); +} + +initSentry(); + +// Right-to-left language support is not supported yet. +disableRTL(); + // Keep the splash screen visible while we fetch resources SplashScreen.preventAutoHideAsync(); @@ -84,17 +86,15 @@ const PureApp = () => ( - - - - - - - - - - - + + + + + + + + + diff --git a/suite-native/app/src/SentryProvider.tsx b/suite-native/app/src/SentryProvider.tsx deleted file mode 100644 index 918d3fc292..0000000000 --- a/suite-native/app/src/SentryProvider.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { ReactNode, useEffect } from 'react'; -import { useSelector } from 'react-redux'; - -import { captureConsoleIntegration } from '@sentry/core'; -import * as Sentry from '@sentry/react-native'; - -import { selectIsAnalyticsEnabled } from '@suite-common/analytics'; -import { getEnv, isDebugEnv, isDetoxTestBuild, isDevelopEnv } from '@suite-native/config'; -import { selectIsOnboardingFinished } from '@suite-native/settings'; - -const initSentry = () => { - Sentry.init({ - dsn: 'https://d473f56df60c4974ae3f3ce00547c2a9@o117836.ingest.sentry.io/4504214699245568', - // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring. - // We recommend adjusting this value in production. - tracesSampleRate: 0.5, - environment: isDetoxTestBuild() ? 'test' : getEnv(), - integrations: [ - captureConsoleIntegration({ - levels: ['error'], - }), - ], - // You can put EXPO_PUBLIC_IS_SENTRY_ON_DEBUG_BUILD_ENABLED=true to `.env.development.local` to debug Sentry locally. - enabled: - !isDebugEnv() || process.env.EXPO_PUBLIC_IS_SENTRY_ON_DEBUG_BUILD_ENABLED === 'true', - }); -}; - -initSentry(); - -export const SentryProvider = ({ children }: { children: ReactNode }) => { - const isOnboardingFinished = useSelector(selectIsOnboardingFinished); - const isAnalyticsEnabled = useSelector(selectIsAnalyticsEnabled); - - useEffect(() => { - // Enforce sentry to be enabled in dev environment because we want to catch all errors - if (!isDevelopEnv() && isOnboardingFinished) { - if (!isAnalyticsEnabled) { - Sentry.close(); - } else { - initSentry(); - } - } - }, [isOnboardingFinished, isAnalyticsEnabled]); - - return <>{children}; -}; diff --git a/suite-native/app/tsconfig.json b/suite-native/app/tsconfig.json index d0a9718761..12b05b37c3 100644 --- a/suite-native/app/tsconfig.json +++ b/suite-native/app/tsconfig.json @@ -70,6 +70,7 @@ { "path": "../navigation" }, { "path": "../notifications" }, { "path": "../receive" }, + { "path": "../sentry" }, { "path": "../settings" }, { "path": "../state" }, { "path": "../storage" }, diff --git a/suite-native/sentry/package.json b/suite-native/sentry/package.json index f21222aa35..2bf15cb483 100644 --- a/suite-native/sentry/package.json +++ b/suite-native/sentry/package.json @@ -11,7 +11,9 @@ "type-check": "yarn g:tsc --build" }, "dependencies": { + "@sentry/core": "8.55.0", "@sentry/react-native": "6.10.0", - "@suite-common/sentry": "workspace:*" + "@suite-common/sentry": "workspace:*", + "@suite-native/config": "workspace:*" } } diff --git a/suite-native/sentry/src/sentry.ts b/suite-native/sentry/src/sentry.ts index ffaf49e3ab..3ae89152eb 100644 --- a/suite-native/sentry/src/sentry.ts +++ b/suite-native/sentry/src/sentry.ts @@ -1,6 +1,8 @@ +import { Options, captureConsoleIntegration } from '@sentry/core'; import * as Sentry from '@sentry/react-native'; import { allowReportTag } from '@suite-common/sentry'; +import { getEnv, isDebugEnv, isDetoxTestBuild } from '@suite-native/config'; export const setSentryContext = Sentry.setContext; @@ -21,3 +23,39 @@ export const allowSentryReport = (value: boolean) => { export const setSentryUser = (instanceId: string) => { Sentry.setUser({ id: instanceId }); }; + +const beforeSend: Options['beforeSend'] = event => { + // sentry events are skipped until user confirm analytics reporting + const allowReport = event.tags?.[allowReportTag]; + + if (allowReport === false) { + return null; + } + // allow report redacted error before confirm status is loaded + if (typeof allowReport === 'undefined') { + delete event.breadcrumbs; + delete event.contexts?.device; + } + + return event; +}; + +export const initSentry = () => { + Sentry.init({ + dsn: 'https://d473f56df60c4974ae3f3ce00547c2a9@o117836.ingest.sentry.io/4504214699245568', + // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring. + // We recommend adjusting this value in production. + tracesSampleRate: 0.5, + environment: isDetoxTestBuild() ? 'test' : getEnv(), + integrations: [ + captureConsoleIntegration({ + levels: ['error'], + }), + ], + beforeSend, + + // You can put EXPO_PUBLIC_IS_SENTRY_ON_DEBUG_BUILD_ENABLED=true to `.env.development.local` to debug Sentry locally. + enabled: + !isDebugEnv() || process.env.EXPO_PUBLIC_IS_SENTRY_ON_DEBUG_BUILD_ENABLED === 'true', + }); +}; diff --git a/suite-native/sentry/tsconfig.json b/suite-native/sentry/tsconfig.json index f28c2c6332..d850759b67 100644 --- a/suite-native/sentry/tsconfig.json +++ b/suite-native/sentry/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "libDev" }, "references": [ - { "path": "../../suite-common/sentry" } + { "path": "../../suite-common/sentry" }, + { "path": "../config" } ] } diff --git a/yarn.lock b/yarn.lock index e1f51e3e79..1c75d848f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9416,7 +9416,6 @@ __metadata: "@react-navigation/native": "npm:6.1.18" "@react-navigation/native-stack": "npm:6.11.0" "@reduxjs/toolkit": "npm:2.6.0" - "@sentry/core": "npm:8.55.0" "@sentry/react-native": "npm:6.10.0" "@shopify/flash-list": "npm:1.7.3" "@shopify/react-native-skia": "npm:^1.11.6" @@ -9463,6 +9462,7 @@ __metadata: "@suite-native/navigation": "workspace:*" "@suite-native/notifications": "workspace:*" "@suite-native/receive": "workspace:*" + "@suite-native/sentry": "workspace:*" "@suite-native/settings": "workspace:*" "@suite-native/state": "workspace:*" "@suite-native/storage": "workspace:*" @@ -10621,8 +10621,10 @@ __metadata: version: 0.0.0-use.local resolution: "@suite-native/sentry@workspace:suite-native/sentry" dependencies: + "@sentry/core": "npm:8.55.0" "@sentry/react-native": "npm:6.10.0" "@suite-common/sentry": "workspace:*" + "@suite-native/config": "workspace:*" languageName: unknown linkType: soft