Skip to content

[Android] TimeToInitialDisplay doesn't track Tab screens from react-navigation #3809

@serzmerz

Description

@serzmerz

OS:

  • Windows
  • MacOS
  • Linux

Platform:

  • iOS
  • Android

SDK:

  • @sentry/react-native (>= 1.0.0)
  • react-native-sentry (<= 0.43.2)

SDK version: 5.22.2

react-native version: 0.73.6

Are you using Expo?

  • Yes
  • No

Are you using sentry.io or on-premise?

  • sentry.io (SaaS)
  • on-premise

If you are using sentry.io, please post a link to your issue so we can take a look:

[Link to issue]

Configuration:

(@sentry/react-native)

export const routingInstrumentation = new NativeSentry.ReactNavigationInstrumentation({
  enableTimeToInitialDisplay: true
});

Sentry.init({
  dsn: Config.get("REACT_APP_SENTRY_DSN"),
  environment: Config.get("ENV"),
  ignoreErrors,
  integrations: [
    new NativeSentry.ReactNativeTracing({
      routingInstrumentation
    })
  ],
  tracesSampleRate: Config.get("ENV") === "prod" && !__DEV__ ? 0.2 : 1,
  _experiments: {
    profilesSampleRate: Config.get("ENV") === "prod" && !__DEV__ ? 0 : 1
  }
});

I have the following issue:

On Android, when enableTimeToInitialDisplay flag is active, sentry doesn't capture initial time on screens from Tab navigator (react-navigation). It is happening in @sentry/react-native/android/src/main/java/io/sentry/react/RNSentryReactFragmentLifecycleTracer.java because:

  1. Tab screen has Class name com.swmansion.rnscreens.ScreenFragment, not com.swmansion.rnscreens.ScreenStackFragment and it doesnt subscribe to eventDispatcher.
  2. Even if I remove this condition, EventDispatcher doesn't report com.swmansion.rnscreens.events.ScreenAppearEvent event, since this event(transitionEnd) only available for Stack screens.

My navigation setup is next: Root stack navigator and one of the screens is TabNavigator

<RootStackNavigator.Navigator screenOptions={rootScreenOptions}>
        {routes.map(({ name, component, options }) => (
          <RootStackNavigator.Screen
            key={name}
            name={name}
            component={component}
            options={options}
          />
        ))}
      </RootStackNavigator.Navigator>
      
      
      
Tabs rendered as a screen inside root stack navigator:

<Tab.Navigator sceneContainerStyle={sceneContainerStyle} screenOptions={tabBarOptions}>
        {tabs.map(({ component, options, listeners, name }) => {
          return (
            <Tab.Screen
              key={name}
              name={name}
              component={component}
              options={options}
              listeners={listeners}
            />
          );
        })}
      </Tab.Navigator>     

Steps to reproduce:

  • Launch the app
  • Tab navigator is active screen
  • Navigate between tabs with tab bar

Actual result:

On android you will get deadline_exceeded for ui.load.initial_display span. (Note: first default screen will be reported correctly, since router fire ScreenAppearEvent for this stack screen). It works as expected on ios with both tab and stack screens.

Screenshot 2024-05-09 at 17 33 30

Expected result:

ui.load.initial_display span captured correctly for tab screens for Android

Next steps:

Have you considered any other options how to trigger navigation end for tab screens? Maybe you know any workarounds?
I can help investigate or provide demo if it will be helpful.
Tabs usually is the most heaviest screens, so we would like to track performance of them, especially for android(which is more slower platform for our app)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status

    Done

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions