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.
This commit is contained in:
Matej Kriz
2025-04-09 17:28:56 +02:00
committed by Matěj Kříž
parent 1003b2e8ce
commit dfd609f5ef
9 changed files with 72 additions and 70 deletions

View File

@@ -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,

View File

@@ -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:*",

View File

@@ -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 = () => (
<GestureHandlerRootView style={{ flex: 1 }}>
<IntlProvider>
<StoreProvider>
<SentryProvider>
<KeyboardProvider>
<SafeAreaProvider>
<StylesProvider>
<NavigationContainerWithAnalytics>
<AppComponent />
</NavigationContainerWithAnalytics>
</StylesProvider>
</SafeAreaProvider>
</KeyboardProvider>
</SentryProvider>
<KeyboardProvider>
<SafeAreaProvider>
<StylesProvider>
<NavigationContainerWithAnalytics>
<AppComponent />
</NavigationContainerWithAnalytics>
</StylesProvider>
</SafeAreaProvider>
</KeyboardProvider>
</StoreProvider>
</IntlProvider>
</GestureHandlerRootView>

View File

@@ -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}</>;
};

View File

@@ -70,6 +70,7 @@
{ "path": "../navigation" },
{ "path": "../notifications" },
{ "path": "../receive" },
{ "path": "../sentry" },
{ "path": "../settings" },
{ "path": "../state" },
{ "path": "../storage" },

View File

@@ -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:*"
}
}

View File

@@ -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',
});
};

View File

@@ -2,6 +2,7 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": { "outDir": "libDev" },
"references": [
{ "path": "../../suite-common/sentry" }
{ "path": "../../suite-common/sentry" },
{ "path": "../config" }
]
}

View File

@@ -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