Skip to content
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

Merged
merged 28 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f71814c
test basic perf setup
brainbicycle Sep 4, 2024
4ff0095
mock sentry constructor to fix tests
brainbicycle Sep 4, 2024
c86bc91
fix mock for routing instrumentation, mock sentry component
brainbicycle Sep 4, 2024
e4da931
remove unnecessary mock from test
brainbicycle Sep 4, 2024
968aadf
test code, remove me
brainbicycle Sep 5, 2024
3908f7b
remove broken sentry display component
brainbicycle Sep 5, 2024
4c2ee19
try enabling user interaction tracing and profiling home
brainbicycle Sep 5, 2024
9ead7a9
register all nav containers
brainbicycle Sep 5, 2024
96df0a4
update app version
brainbicycle Sep 5, 2024
20fda46
wrap app with sentry as recommended
brainbicycle Sep 5, 2024
9245bf3
setup sentry before wrapping app, delete now unused hook
brainbicycle Sep 5, 2024
e81e16d
try updating how we create refs
brainbicycle Sep 5, 2024
187031a
stop trying to register other nav containers
brainbicycle Sep 6, 2024
eb45a02
undo accidental changes
brainbicycle Sep 6, 2024
2949ef2
fix event reporting for screens in tabs
brainbicycle Sep 6, 2024
da81cf2
clean up sentry set up a bit
brainbicycle Sep 7, 2024
e51d6f5
move setup to a component to get refresh on toggle change
brainbicycle Sep 7, 2024
2382b3f
fix bootstrap setup
brainbicycle Sep 7, 2024
c4dc827
turn off debug and lower sample rate
brainbicycle Sep 7, 2024
ef6f770
revert me: update sample rate for testing
brainbicycle Sep 7, 2024
9364238
fix hardcoded env
brainbicycle Sep 7, 2024
557ce43
move sentry setup back to global function
brainbicycle Sep 9, 2024
2c1695e
update dev tool to allow easier debugging
brainbicycle Sep 9, 2024
bb43913
Merge remote-tracking branch 'origin/main' into brian/sentry-performance
brainbicycle Sep 9, 2024
94b8068
move sentry mock to setup jest
brainbicycle Sep 9, 2024
bb11a16
fix broken tests
brainbicycle Sep 10, 2024
08cc5d3
Merge remote-tracking branch 'origin/main' into brian/sentry-performance
brainbicycle Sep 10, 2024
1f13bf4
safer unwrap for main stack
brainbicycle Sep 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"appName": "eigen",
"version": "8.50.0",
"version": "8.51.0",
"isAndroidBeta": false,
"codePushReleaseName": "none",
"codePushDist": "none"
Expand Down
2 changes: 1 addition & 1 deletion index-common.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ if (__DEV__) {
} catch {}
}

require("./src/app/system/errorReporting/sentrySetup").setupSentry({ environment: "bootstrap" })
require("./src/app/system/errorReporting/setupSentry").setupSentry({ environment: "bootstrap" })
Copy link
Contributor Author

@brainbicycle brainbicycle Sep 8, 2024

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.

import "react-native-url-polyfill/auto"
const { AppRegistry } = require("react-native")

Expand Down
8 changes: 5 additions & 3 deletions src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { GoogleSignin } from "@react-native-google-signin/google-signin"
import * as Sentry from "@sentry/react-native"
import { GlobalStore } 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 { SentrySetup } from "app/system/errorReporting/Components/SentrySetup"
import { ModalStack } from "app/system/navigation/ModalStack"
import { usePurgeCacheOnAppUpdate } from "app/system/relay/usePurgeCacheOnAppUpdate"
import { useDevToggle } from "app/utils/hooks/useDevToggle"
Expand Down Expand Up @@ -85,7 +86,6 @@ const Main = () => {

const fpsCounter = useDevToggle("DTFPSCounter")

useErrorReporting()
useStripeConfig()
useSiftConfig()
useWebViewCookies()
Expand Down Expand Up @@ -154,6 +154,7 @@ const Main = () => {
const InnerApp = () => (
<Providers>
<AsyncStorageDevtools />
<SentrySetup />
brainbicycle marked this conversation as resolved.
Show resolved Hide resolved

<DevMenuWrapper>
<Main />
Expand All @@ -163,4 +164,5 @@ const InnerApp = () => (
</Providers>
)

export const App = codePush(codePushOptions)(InnerApp)
const SentryApp = Sentry.wrap(InnerApp)
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

export const App = codePush(codePushOptions)(SentryApp)
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,6 @@ const TestWrapper: typeof AutosuggestResults = (props) => (

jest.mock("lodash/throttle", () => (f: any) => f)

jest.mock("@sentry/react-native", () => ({ init() {}, captureMessage() {} }))

// app/Scenes/Search/RecentSearches.tsx
jest.mock("app/Scenes/Search/RecentSearches", () => {
const notifyRecentSearch = jest.fn()
Expand Down
5 changes: 4 additions & 1 deletion src/app/Scenes/Home/HomeContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as Sentry from "@sentry/react-native"
import { HomeQueryRenderer } from "app/Scenes/Home/Home"
import { HomeViewScreen } from "app/Scenes/HomeView/HomeView"
import { Playground } from "app/Scenes/Playground/Playground"
Expand All @@ -7,7 +8,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")
Expand Down Expand Up @@ -38,3 +39,5 @@ export const HomeContainer = () => {

return <HomeQueryRenderer />
}

export const HomeContainer = Sentry.withProfiler(InnerHomeContainer)
Copy link
Contributor Author

@brainbicycle brainbicycle Sep 7, 2024

Choose a reason for hiding this comment

The 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

2 changes: 1 addition & 1 deletion src/app/system/devTools/DevMenu/Components/DevTools.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { DevToggleName, devToggles } from "app/store/config/features"
import { Versions } from "app/store/migration"
import { DevMenuButtonItem } from "app/system/devTools/DevMenu/Components/DevMenuButtonItem"
import { DevToggleItem } from "app/system/devTools/DevMenu/Components/DevToggleItem"
import { eigenSentryReleaseName } from "app/system/errorReporting/sentrySetup"
import { eigenSentryReleaseName } from "app/system/errorReporting/setupSentry"
import { dismissModal, navigate } from "app/system/navigation/navigate"
import { RelayCache } from "app/system/relay/RelayCache"
import { useUnleashEnvironment } from "app/utils/experiments/hooks"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { GlobalStore } from "app/store/GlobalStore"
import { setupSentry } from "app/system/errorReporting/setupSentry"
import { useDevToggle } from "app/utils/hooks/useDevToggle"
import { useEffect } from "react"
import { setupSentry } from "./sentrySetup"

export function useErrorReporting() {
export const SentrySetup = () => {
const environment = GlobalStore.useAppState((store) => store.devicePrefs.environment.env)
const captureExceptionsInSentryOnDev = useDevToggle("DTCaptureExceptionsInSentryOnDev")
const captureExceptions = !__DEV__ ? true : captureExceptionsInSentryOnDev

useEffect(() => {
if (captureExceptions) {
setupSentry({ environment, captureExceptionsInSentryOnDev })
}
}, [environment, captureExceptions])
setupSentry({
environment,
captureExceptionsInSentryOnDev: captureExceptions,
})
}, [environment, captureExceptionsInSentryOnDev])
return null
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
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 = () => {
Expand Down Expand Up @@ -59,6 +67,37 @@ export function setupSentry(props: SetupSentryProps = {}) {
autoSessionTracking: true,
enableWatchdogTerminationTracking: false,
attachStacktrace: true,
tracesSampleRate: 1.0,
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.
*/
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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,
})
}
3 changes: 3 additions & 0 deletions src/app/system/navigation/ModalStack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { LoadingSpinner } from "app/Components/Modals/LoadingModal"
import { __unsafe_mainModalStackRef } from "app/NativeModules/ARScreenPresenterModule"
import { LegacyNativeModules } from "app/NativeModules/LegacyNativeModules"
import { GlobalStore } from "app/store/GlobalStore"
import { routingInstrumentation } from "app/system/errorReporting/setupSentry"
import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag"
import { logNavigation } from "app/utils/loggers"
import { Platform } from "react-native"
Expand Down Expand Up @@ -48,6 +49,8 @@ export const ModalStack: React.FC = ({ children }) => {
ref={__unsafe_mainModalStackRef}
initialState={initialState}
onReady={() => {
routingInstrumentation.registerNavigationContainer(__unsafe_mainModalStackRef)

setNavigationReady({ isNavigationReady: true })

if (trackSiftAndroid) {
Expand Down
4 changes: 2 additions & 2 deletions src/app/utils/AboveTheFoldQueryRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { renderWithPlaceholder } from "./renderWithPlaceholder"

interface AboveTheFoldQueryRendererProps<
AboveQuery extends OperationType,
BelowQuery extends OperationType
BelowQuery extends OperationType,
> {
environment: Environment | MockEnvironment
above: {
Expand Down Expand Up @@ -50,7 +50,7 @@ interface RenderArgs<Response> {
*/
export function AboveTheFoldQueryRenderer<
AboveQuery extends OperationType,
BelowQuery extends OperationType
BelowQuery extends OperationType,
>(props: AboveTheFoldQueryRendererProps<AboveQuery, BelowQuery>) {
const [aboveArgs, setAboveArgs] = useState<null | RenderArgs<AboveQuery["response"]>>(null)
const [belowArgs, setBelowArgs] = useState<null | RenderArgs<BelowQuery["response"]>>(null)
Expand Down
6 changes: 6 additions & 0 deletions src/setupJest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,12 @@ jest.mock("@sentry/react-native", () => ({
addBreadcrumb() {},
withScope() {},
Severity: "info",
ReactNavigationInstrumentation: jest.fn().mockImplementation(() => ({
registerNavigationContainer: jest.fn(),
})),
wrap: jest.fn().mockImplementation((component) => component),
withProfiler: jest.fn().mockImplementation((component) => component),
TimeToFullDisplay: () => null,
}))

jest.mock("@react-native-mapbox-gl/maps", () => ({
Expand Down