-
Notifications
You must be signed in to change notification settings - Fork 582
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: enable sentry performance metrics #10720
Changes from 27 commits
f71814c
4ff0095
c86bc91
e4da931
968aadf
3908f7b
4c2ee19
9ead7a9
96df0a4
20fda46
9245bf3
e81e16d
187031a
eb45a02
2949ef2
da81cf2
e51d6f5
2382b3f
c4dc827
ef6f770
9364238
557ce43
2c1695e
bb43913
94b8068
bb11a16
08cc5d3
1f13bf4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,12 @@ | ||
import { GoogleSignin } from "@react-native-google-signin/google-signin" | ||
import { GlobalStore } from "app/store/GlobalStore" | ||
import * as Sentry from "@sentry/react-native" | ||
import { GlobalStore, unsafe__getEnvironment, unsafe_getDevToggle } from "app/store/GlobalStore" | ||
import { codePushOptions } from "app/system/codepush" | ||
import { AsyncStorageDevtools } from "app/system/devTools/AsyncStorageDevTools" | ||
import { DevMenuWrapper } from "app/system/devTools/DevMenu/DevMenuWrapper" | ||
import { setupFlipper } from "app/system/devTools/flipper" | ||
import { useRageShakeDevMenu } from "app/system/devTools/useRageShakeDevMenu" | ||
import { useErrorReporting } from "app/system/errorReporting/hooks" | ||
import { setupSentry } from "app/system/errorReporting/setupSentry" | ||
import { ModalStack } from "app/system/navigation/ModalStack" | ||
import { usePurgeCacheOnAppUpdate } from "app/system/relay/usePurgeCacheOnAppUpdate" | ||
import { useDevToggle } from "app/utils/hooks/useDevToggle" | ||
|
@@ -54,6 +55,14 @@ if (__DEV__) { | |
|
||
setupFlipper() | ||
|
||
// Sentry must be setup early in the app lifecycle to hook into navigation | ||
const debugSentry = unsafe_getDevToggle("DTDebugSentry") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👏 gread idea adding a dev toggle |
||
const environment = unsafe__getEnvironment() | ||
setupSentry({ | ||
environment: environment.env, | ||
debug: debugSentry, | ||
}) | ||
|
||
addTrackingProvider(SEGMENT_TRACKING_PROVIDER, SegmentTrackingProvider) | ||
addTrackingProvider("console", ConsoleTrackingProvider) | ||
|
||
|
@@ -85,7 +94,6 @@ const Main = () => { | |
|
||
const fpsCounter = useDevToggle("DTFPSCounter") | ||
|
||
useErrorReporting() | ||
useStripeConfig() | ||
useSiftConfig() | ||
useWebViewCookies() | ||
|
@@ -163,4 +171,5 @@ const InnerApp = () => ( | |
</Providers> | ||
) | ||
|
||
export const App = codePush(codePushOptions)(InnerApp) | ||
const SentryApp = Sentry.wrap(InnerApp) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. possibly we should wrap the Main component rather than whole app 👀 double check. this may need to happen after setup is called There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is recommended by the docs though: https://docs.sentry.io/platforms/react-native/tracing/instrumentation/automatic-instrumentation/ |
||
export const App = codePush(codePushOptions)(SentryApp) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
import * as Sentry from "@sentry/react-native" | ||
import { ArtsyNativeModule } from "app/NativeModules/ArtsyNativeModule" | ||
import { HomeQueryRenderer } from "app/Scenes/Home/Home" | ||
import { HomeViewScreen } from "app/Scenes/HomeView/HomeView" | ||
|
@@ -8,7 +9,7 @@ import { useDevToggle } from "app/utils/hooks/useDevToggle" | |
import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" | ||
import { useEffect } from "react" | ||
|
||
export const HomeContainer = () => { | ||
export const InnerHomeContainer = () => { | ||
const artQuizState = GlobalStore.useAppState((state) => state.auth.onboardingArtQuizState) | ||
const isNavigationReady = GlobalStore.useAppState((state) => state.sessionState.isNavigationReady) | ||
const showPlayground = useDevToggle("DTShowPlayground") | ||
|
@@ -42,3 +43,5 @@ export const HomeContainer = () => { | |
return <HomeQueryRenderer /> | ||
} | ||
} | ||
|
||
export const HomeContainer = Sentry.withProfiler(InnerHomeContainer) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not 100% this is doing anything currently, double check, this should give us more react profile style metrics in home screen transactions, but I didn't see much of a difference before and after |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
import { useToast } from "app/Components/Toast/toastHook" | ||
import { GlobalStore } from "app/store/GlobalStore" | ||
import { GlobalStore, unsafe__getEnvironment } from "app/store/GlobalStore" | ||
import { setupSentry } from "app/system/errorReporting/setupSentry" | ||
import { echoLaunchJson } from "app/utils/jsonFiles" | ||
import Config from "react-native-config" | ||
|
||
interface FeatureDescriptorCommonTypes { | ||
/** Provide a short description for the Dev Menu. */ | ||
|
@@ -330,8 +332,29 @@ export const devToggles: { [key: string]: DevToggleDescriptor } = { | |
DTShowInstagramShot: { | ||
description: "Instagram viewshot debug", | ||
}, | ||
DTCaptureExceptionsInSentryOnDev: { | ||
description: "Capture exceptions in Sentry on DEV", | ||
DTDebugSentry: { | ||
description: "Enable sentry debug mode and send exceptions to sentry", | ||
onChange: (value, { toast }) => { | ||
if (!Config.SENTRY_DSN) { | ||
toast.show( | ||
`No Sentry DSN available ${__DEV__ ? "Set it in .env.shared and re-build the app." : ""}`, | ||
"middle" | ||
) | ||
return | ||
} | ||
|
||
const environment = unsafe__getEnvironment() | ||
setupSentry({ | ||
environment: environment.env, | ||
debug: value, | ||
}) | ||
|
||
if (value) { | ||
toast.show("Sentry debugging enabled", "middle") | ||
} else { | ||
toast.show("Sentry debugging disabled", "middle") | ||
} | ||
}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since sentry set up is no longer in a hook because it needs to be earlier in the lifecycle, call it manually on change. |
||
}, | ||
DTFPSCounter: { | ||
description: "FPS counter", | ||
|
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import { findFocusedRoute } from "@react-navigation/native" | ||
import * as Sentry from "@sentry/react-native" | ||
import { TransactionContext } from "@sentry/types" | ||
import { __unsafe_mainModalStackRef } from "app/NativeModules/ARScreenPresenterModule" | ||
import { BottomTabOption } from "app/Scenes/BottomTabs/BottomTabType" | ||
import { appJson } from "app/utils/jsonFiles" | ||
import { Platform } from "react-native" | ||
import Config from "react-native-config" | ||
import DeviceInfo from "react-native-device-info" | ||
|
||
export const routingInstrumentation = new Sentry.ReactNavigationInstrumentation({ | ||
enableTimeToInitialDisplay: true, | ||
}) | ||
|
||
// important! this must match the release version specified | ||
// in fastfile in order for sourcemaps/sentry stacktraces to work | ||
export const eigenSentryReleaseName = () => { | ||
const codePushReleaseName = appJson().codePushReleaseName | ||
if (codePushReleaseName && codePushReleaseName !== "none") { | ||
return codePushReleaseName | ||
} else { | ||
const prefix = Platform.OS === "ios" ? "ios" : "android" | ||
const buildNumber = DeviceInfo.getBuildNumber() | ||
const version = DeviceInfo.getVersion() | ||
return prefix + "-" + version + "-" + buildNumber | ||
} | ||
} | ||
|
||
const eigenSentryDist = () => { | ||
const codePushDist = appJson().codePushDist | ||
if (codePushDist && codePushDist !== "none") { | ||
return codePushDist | ||
} else { | ||
return DeviceInfo.getBuildNumber() | ||
} | ||
} | ||
|
||
interface SetupSentryProps extends Partial<Sentry.ReactNativeOptions> { | ||
debug?: boolean | ||
} | ||
|
||
export function setupSentry(props: SetupSentryProps = { debug: false }) { | ||
const sentryDSN = Config.SENTRY_DSN | ||
const ossUser = Config.OSS === "true" | ||
|
||
// In DEV, enabling this will clober stack traces in errors and logs, obscuring | ||
// the source of the error. So we disable it in dev mode. | ||
if (__DEV__ && !props.debug) { | ||
console.log("[dev] Sentry disabled in dev mode.") | ||
return | ||
} | ||
|
||
if (ossUser) { | ||
console.log("[oss] Sentry disabled in for oss user.") | ||
return | ||
} | ||
|
||
if (!sentryDSN) { | ||
console.error("Sentry DSN not set!!") | ||
return | ||
} | ||
|
||
Sentry.init({ | ||
dsn: sentryDSN, | ||
release: eigenSentryReleaseName(), | ||
dist: eigenSentryDist(), | ||
enableAutoSessionTracking: true, | ||
autoSessionTracking: true, | ||
enableWatchdogTerminationTracking: false, | ||
attachStacktrace: true, | ||
tracesSampleRate: props.debug ? 1.0 : 0.1, | ||
debug: props.debug, | ||
integrations: [ | ||
new Sentry.ReactNativeTracing({ | ||
enableUserInteractionTracing: true, | ||
routingInstrumentation, | ||
beforeNavigate: (context: TransactionContext) => { | ||
/** | ||
* This is a hack because our navigation setup is weird. | ||
* We have a main modal stack at the root and then every screen presented | ||
* in a tab gets its own stack. Sentry is registering every screen in a tab as | ||
* a screen transaction for the root screen. For example, tapping on an | ||
* artwork in the home screen will fire as `screen:home` instead of `screen:artwork`. | ||
* To fix it we find the focused route and update the context name to the correct screen name. | ||
* This should be updated if we change our navigation setup. | ||
*/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. funkiness do to our nav set up, let me know if the comment makes sense, the good news is most screens fire and get registered as transactions but we need to update the names manually |
||
if (__unsafe_mainModalStackRef.current) { | ||
brainbicycle marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const mainNavState = __unsafe_mainModalStackRef.current?.getState() | ||
const focusedRoute = findFocusedRoute(mainNavState) | ||
const routeParams = focusedRoute?.params as { moduleName?: string } | ||
if (routeParams?.moduleName && !(routeParams?.moduleName in BottomTabOption)) { | ||
context.name = `screen:${routeParams.moduleName.toLowerCase()}` | ||
} | ||
context.sampled = true | ||
} else { | ||
// for now not sampling off main modal stack to avoid noise | ||
context.sampled = false | ||
} | ||
return context | ||
}, | ||
}), | ||
], | ||
...props, | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should probably remove this, I will do as separate pr to avoid too much in this one. I am guessing the intention was to initialize sentry early to catch errors early in app lifecycle, but I think we pay for it with complexity in our reporting having an extra env, and initializing 2x might be leading to subtler bugs in our reporting.