From 57ec77b3fa4fc7abcf580b41c1930f567238efdd Mon Sep 17 00:00:00 2001 From: Cristiano Tofani Date: Sat, 5 Oct 2024 09:59:55 +0200 Subject: [PATCH] feat: [IOPLT-306] Setup the Sentry performance monitoring and navigation tracing (#6114) ## Short description This PR aims to setup sentry performance monitoring on the app ## List of changes proposed in this pull request - Changes on Sentry initialization ## How to test Check navigation events are properly sent to sentry --------- Co-authored-by: Andrea --- index.js | 2 +- ts/App.tsx | 21 +++++++++++++++++++-- ts/RootContainer.tsx | 10 ++++++++-- ts/navigation/AppStackNavigator.tsx | 20 +++++++++++++++++--- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index bb56c1c2e9d..f19f4e66a0d 100644 --- a/index.js +++ b/index.js @@ -18,7 +18,7 @@ import { setNativeExceptionHandler } from "react-native-exception-handler"; -import { App } from "./ts/App"; +import App from "./ts/App"; import { mixpanel } from "./ts/mixpanel"; import { name as appName } from "./app.json"; diff --git a/ts/App.tsx b/ts/App.tsx index f43522feb34..6b31756ad92 100644 --- a/ts/App.tsx +++ b/ts/App.tsx @@ -17,6 +17,10 @@ import { LightModalProvider } from "./components/ui/LightModal"; import { sentryDsn } from "./config"; import { isDevEnv } from "./utils/environment"; +export const routingInstrumentation = Sentry.reactNavigationIntegration({ + enableTimeToInitialDisplay: true +}); + const removeUserFromEvent = (event: ErrorEvent | TransactionEvent) => { // console.log(JSON.stringify(event)); // Modify or drop the event here @@ -37,7 +41,12 @@ Sentry.init({ beforeSendTransaction(event) { return removeUserFromEvent(event); }, + integrations: integrations => [ + ...integrations, + new Sentry.ReactNativeTracing({ routingInstrumentation }) + ], enabled: !isDevEnv, + tracesSampleRate: 0.3, sampleRate: 0.3 }); @@ -49,7 +58,7 @@ export type AppDispatch = typeof store.dispatch; * Main component of the application * @constructor */ -export const App = (): JSX.Element => ( +const App = (): JSX.Element => ( @@ -59,7 +68,9 @@ export const App = (): JSX.Element => ( - + @@ -70,3 +81,9 @@ export const App = (): JSX.Element => ( ); + +/** + * We wrap the main app component with the sentry utility function to handle + * the Performance monitoring + */ +export default Sentry.wrap(App); diff --git a/ts/RootContainer.tsx b/ts/RootContainer.tsx index 0146afe9efa..6885dc89751 100644 --- a/ts/RootContainer.tsx +++ b/ts/RootContainer.tsx @@ -8,6 +8,7 @@ import { Platform, StatusBar } from "react-native"; +import { ReactNavigationInstrumentation } from "@sentry/react-native"; import SplashScreen from "react-native-splash-screen"; import { connect } from "react-redux"; import configurePushNotifications from "./features/pushNotifications/utils/configurePushNotification"; @@ -29,7 +30,10 @@ import { import { GlobalState } from "./store/reducers/types"; import customVariables from "./theme/variables"; -type Props = ReturnType & typeof mapDispatchToProps; +type Props = ReturnType & + typeof mapDispatchToProps & { + routingInstumentation: ReactNavigationInstrumentation; + }; /** * The main container of the application with: @@ -99,7 +103,9 @@ class RootContainer extends React.PureComponent { /> {Platform.OS === "android" && } - + {/* When debug mode is enabled, the following information is displayed: diff --git a/ts/navigation/AppStackNavigator.tsx b/ts/navigation/AppStackNavigator.tsx index 4884a24f33b..bb60e33ec3f 100644 --- a/ts/navigation/AppStackNavigator.tsx +++ b/ts/navigation/AppStackNavigator.tsx @@ -7,6 +7,7 @@ import { } from "@react-navigation/native"; import React, { useRef } from "react"; import { View } from "react-native"; +import { ReactNavigationInstrumentation } from "@sentry/react-native"; import { useStoredExperimentalDesign } from "../common/context/DSExperimentalContext"; import LoadingSpinnerOverlay from "../components/LoadingSpinnerOverlay"; import { cgnLinkingOptions } from "../features/bonus/cgn/navigation/navigator"; @@ -79,7 +80,11 @@ export const AppStackNavigator = (): React.ReactElement => { return ; }; -const InnerNavigationContainer = (props: { children: React.ReactElement }) => { +type InnerNavigationContainerProps = React.PropsWithChildren<{ + routingInstrumentation?: ReactNavigationInstrumentation; +}>; + +const InnerNavigationContainer = (props: InnerNavigationContainerProps) => { const routeNameRef = useRef(); const dispatch = useIODispatch(); const store = useIOStore(); @@ -164,6 +169,11 @@ const InnerNavigationContainer = (props: { children: React.ReactElement }) => { linking={linking} fallback={} onReady={() => { + if (props.routingInstrumentation) { + props.routingInstrumentation.registerNavigationContainer( + navigationRef + ); + } NavigationService.setNavigationReady(); routeNameRef.current = navigationRef.current?.getCurrentRoute()?.name; }} @@ -189,8 +199,12 @@ const InnerNavigationContainer = (props: { children: React.ReactElement }) => { * Wraps the NavigationContainer with the AppStackNavigator (Root navigator of the app) * @constructor */ -export const IONavigationContainer = () => ( - +export const IONavigationContainer = ({ + routingInstrumentation +}: { + routingInstrumentation: ReactNavigationInstrumentation; +}) => ( + );