diff --git a/CHANGELOG.md b/CHANGELOG.md index 168c83891..65fb381f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,16 @@ module.exports = withSentryConfig(getDefaultConfig(__dirname), { includeWebReplay: true }); ``` +### Changes + +- React Native Tracing Deprecations ([#4073](https://github.com/getsentry/sentry-react-native/pull/4073)) + - `new ReactNativeTracing` to `reactNativeTracingIntegration()` + - `new ReactNavigationInstrumentation` to `reactNativeTracingIntegration()`. + - `new ReactNativeNavigationInstrumentation` to `reactNativeTracingIntegration()`. + - `ReactNavigationV4Instrumentation` won't be supported in the next major SDK version, upgrade to `react-navigation@5` or newer. + - `RoutingInstrumentation` and `RoutingInstrumentationInstance` replace by `Integration` interface from `@sentry/types`. + - `enableAppStartTracking`, `enableNativeFramesTracking`, `enableStallTracking`, `enableUserInteractionTracing` moved to `Sentry.init({})` root options. + ## 5.31.1 ### Fixes diff --git a/samples/expo/app/_layout.tsx b/samples/expo/app/_layout.tsx index fddab42cf..f9b3532e7 100644 --- a/samples/expo/app/_layout.tsx +++ b/samples/expo/app/_layout.tsx @@ -21,7 +21,7 @@ LogBox.ignoreAllLogs(); // Prevent the splash screen from auto-hiding before asset loading is complete. SplashScreen.preventAutoHideAsync(); -const routingInstrumentation = new Sentry.ReactNavigationInstrumentation({ +const routingInstrumentation = Sentry.reactNavigationIntegration({ enableTimeToInitialDisplay: !isExpoGo(), // This is not supported in Expo Go. }); @@ -55,7 +55,7 @@ process.env.EXPO_SKIP_DURING_EXPORT !== 'true' && Sentry.init({ failedRequestTargets: [/.*/], }), Sentry.metrics.metricsAggregatorIntegration(), - new Sentry.ReactNativeTracing({ + Sentry.reactNativeTracingIntegration({ routingInstrumentation, }), ); diff --git a/samples/react-native/src/App.tsx b/samples/react-native/src/App.tsx index 191775349..31b3b89e1 100644 --- a/samples/react-native/src/App.tsx +++ b/samples/react-native/src/App.tsx @@ -38,11 +38,10 @@ LogBox.ignoreAllLogs(); const isMobileOs = Platform.OS === 'android' || Platform.OS === 'ios'; -const reactNavigationInstrumentation = - new Sentry.ReactNavigationInstrumentation({ - routeChangeTimeoutMs: 500, // How long it will wait for the route change to complete. Default is 1000ms - enableTimeToInitialDisplay: isMobileOs, - }); +const reactNavigationInstrumentation = Sentry.reactNavigationIntegration({ + routeChangeTimeoutMs: 500, // How long it will wait for the route change to complete. Default is 1000ms + enableTimeToInitialDisplay: isMobileOs, +}); Sentry.init({ // Replace the example DSN below with your own DSN: @@ -64,13 +63,13 @@ Sentry.init({ didCallNativeInit, ); }, + enableUserInteractionTracing: true, integrations(integrations) { integrations.push( - new Sentry.ReactNativeTracing({ + Sentry.reactNativeTracingIntegration({ // The time to wait in ms until the transaction will be finished, For testing, default is 1000 ms idleTimeout: 5000, routingInstrumentation: reactNavigationInstrumentation, - enableUserInteractionTracing: true, ignoreEmptyBackNavigationTransactions: true, beforeNavigate: (context: Sentry.ReactNavigationTransactionContext) => { // Example of not sending a transaction for the screen with the name "Manual Tracker" diff --git a/src/js/client.ts b/src/js/client.ts index e22eceebd..278c9e0cb 100644 --- a/src/js/client.ts +++ b/src/js/client.ts @@ -129,7 +129,8 @@ export class ReactNativeClient extends BaseClient { if (routingName) { this.addIntegration(createIntegration(routingName)); } - const enableUserInteractionTracing = tracing?.options.enableUserInteractionTracing; + const enableUserInteractionTracing = + this._options.enableUserInteractionTracing ?? tracing?.options.enableUserInteractionTracing; if (enableUserInteractionTracing) { this.addIntegration(createIntegration('ReactNativeUserInteractionTracing')); } diff --git a/src/js/index.ts b/src/js/index.ts index 1dee81adf..a261201b4 100644 --- a/src/js/index.ts +++ b/src/js/index.ts @@ -91,11 +91,13 @@ export { TouchEventBoundary, withTouchEventBoundary } from './touchevents'; export { ReactNativeTracing, ReactNavigationV4Instrumentation, - // eslint-disable-next-line deprecation/deprecation ReactNavigationV5Instrumentation, ReactNavigationInstrumentation, ReactNativeNavigationInstrumentation, RoutingInstrumentation, + reactNativeTracingIntegration, + reactNavigationIntegration, + reactNativeNavigationIntegration, sentryTraceGesture, TimeToInitialDisplay, TimeToFullDisplay, diff --git a/src/js/integrations/default.ts b/src/js/integrations/default.ts index 3aab4cd55..bcbac5c2c 100644 --- a/src/js/integrations/default.ts +++ b/src/js/integrations/default.ts @@ -85,7 +85,10 @@ export function getDefaultIntegrations(options: ReactNativeClientOptions): Integ if (options.attachViewHierarchy) { integrations.push(viewHierarchyIntegration()); } - if (options._experiments && typeof options._experiments.profilesSampleRate === 'number') { + if ( + options.profilesSampleRate ?? + (options._experiments && typeof options._experiments.profilesSampleRate === 'number') + ) { integrations.push(hermesProfilingIntegration()); } } diff --git a/src/js/options.ts b/src/js/options.ts index 07815504c..9a4e409fe 100644 --- a/src/js/options.ts +++ b/src/js/options.ts @@ -204,6 +204,44 @@ export interface BaseReactNativeOptions { */ beforeScreenshot?: (event: Event, hint: EventHint) => boolean; + /** + * The sample rate for profiling + * 1.0 will profile all transactions and 0 will profile none. + */ + profilesSampleRate?: number; + + /** + * Track the app start time by adding measurements to the first route transaction. If there is no routing instrumentation + * an app start transaction will be started. + * + * Requires performance monitoring to be enabled. + * + * @default true + */ + enableAppStartTracking?: boolean; + + /** + * Track the slow and frozen frames in the application. Enabling this options will add + * slow and frozen frames measurements to all created root spans (transactions). + * + * @default true + */ + enableNativeFramesTracking?: boolean; + + /** + * Track when and how long the JS event loop stalls for. Adds stalls as measurements to all transactions. + * + * @default true + */ + enableStallTracking?: boolean; + + /** + * Trace User Interaction events like touch and gestures. + * + * @default false + */ + enableUserInteractionTracing?: boolean; + /** * Options which are in beta, or otherwise not guaranteed to be stable. */ @@ -211,8 +249,7 @@ export interface BaseReactNativeOptions { [key: string]: unknown; /** - * The sample rate for profiling - * 1.0 will profile all transactions and 0 will profile none. + * @deprecated Use `profilesSampleRate` in the options root instead. */ profilesSampleRate?: number; diff --git a/src/js/profiling/integration.ts b/src/js/profiling/integration.ts index 8fb6b7bce..9fd2d0a0e 100644 --- a/src/js/profiling/integration.ts +++ b/src/js/profiling/integration.ts @@ -12,6 +12,7 @@ import type { import { logger, uuid4 } from '@sentry/utils'; import { Platform } from 'react-native'; +import type { ReactNativeClient } from '../client'; import { isHermesEnabled } from '../utils/environment'; import { NATIVE } from '../wrapper'; import { PROFILE_QUEUE } from './cache'; @@ -109,13 +110,16 @@ export const hermesProfilingIntegration: IntegrationFn = () => { return false; } - const client = getClient(); + const client = getClient(); const options = client && client.getOptions(); const profilesSampleRate = - options && options._experiments && typeof options._experiments.profilesSampleRate === 'number' - ? options._experiments.profilesSampleRate - : undefined; + options && + ((typeof options.profilesSampleRate === 'number' && options.profilesSampleRate) || + (options._experiments && + typeof options._experiments.profilesSampleRate === 'number' && + options._experiments.profilesSampleRate) || + undefined); if (profilesSampleRate === undefined) { logger.log('[Profiling] Profiling disabled, enable it by setting `profilesSampleRate` option to SDK init call.'); return false; diff --git a/src/js/tracing/index.ts b/src/js/tracing/index.ts index 7fd0312a6..c9fd6e4cf 100644 --- a/src/js/tracing/index.ts +++ b/src/js/tracing/index.ts @@ -1,15 +1,16 @@ -export { ReactNativeTracing } from './reactnativetracing'; +export { ReactNativeTracing, reactNativeTracingIntegration } from './reactnativetracing'; export type { RoutingInstrumentationInstance } from './routingInstrumentation'; export { RoutingInstrumentation } from './routingInstrumentation'; export { ReactNavigationInstrumentation, + reactNavigationIntegration, // eslint-disable-next-line deprecation/deprecation ReactNavigationV5Instrumentation, } from './reactnavigation'; export { ReactNavigationV4Instrumentation } from './reactnavigationv4'; -export { ReactNativeNavigationInstrumentation } from './reactnativenavigation'; +export { ReactNativeNavigationInstrumentation, reactNativeNavigationIntegration } from './reactnativenavigation'; export type { ReactNavigationCurrentRoute, ReactNavigationRoute, ReactNavigationTransactionContext } from './types'; diff --git a/src/js/tracing/reactnativenavigation.ts b/src/js/tracing/reactnativenavigation.ts index 29d83fbc5..983757b1a 100644 --- a/src/js/tracing/reactnativenavigation.ts +++ b/src/js/tracing/reactnativenavigation.ts @@ -68,6 +68,17 @@ export interface NavigationDelegate { * - `_onComponentWillAppear` is then called AFTER the state change happens due to a dispatch and sets the route context onto the active transaction. * - If `_onComponentWillAppear` isn't called within `options.routeChangeTimeoutMs` of the dispatch, then the transaction is not sampled and finished. */ +export const reactNativeNavigationIntegration = ( + options: Partial & { + navigation: NavigationDelegate; + }, +): ReactNativeNavigationInstrumentation => { + return new ReactNativeNavigationInstrumentation(options.navigation, options); +}; + +/** + * @deprecated Use `Sentry.reactNativeNavigationIntegration({ navigation })` instead. + */ export class ReactNativeNavigationInstrumentation extends InternalRoutingInstrumentation { public static instrumentationName: string = 'react-native-navigation'; diff --git a/src/js/tracing/reactnativetracing.ts b/src/js/tracing/reactnativetracing.ts index 952fabc5c..dcbcbb5b3 100644 --- a/src/js/tracing/reactnativetracing.ts +++ b/src/js/tracing/reactnativetracing.ts @@ -13,8 +13,10 @@ import type { } from '@sentry/types'; import { logger } from '@sentry/utils'; +import type { ReactNativeClient } from '../client'; import { APP_START_COLD, APP_START_WARM } from '../measurements'; import type { NativeAppStartResponse } from '../NativeRNSentry'; +import type { ReactNativeClientOptions } from '../options'; import type { RoutingInstrumentationInstance } from '../tracing/routingInstrumentation'; import { NATIVE } from '../wrapper'; import { NativeFramesInstrumentation } from './nativeframes'; @@ -30,6 +32,10 @@ import { setSpanDurationAsMeasurement, } from './utils'; +export const reactNativeTracingIntegration = (options?: Partial): ReactNativeTracing => { + return new ReactNativeTracing(options); +}; + export interface ReactNativeTracingOptions extends RequestInstrumentationOptions { /** * @deprecated Replaced by idleTimeoutMs @@ -85,25 +91,22 @@ export interface ReactNativeTracingOptions extends RequestInstrumentationOptions beforeNavigate: BeforeNavigate; /** - * Track the app start time by adding measurements to the first route transaction. If there is no routing instrumentation - * an app start transaction will be started. - * - * Default: true + * @deprecated Use `Sentry.init({ enableAppStartTracking })` instead. */ enableAppStartTracking: boolean; /** - * Track slow/frozen frames from the native layer and adds them as measurements to all transactions. + * @deprecated Use `Sentry.init({ enableNativeFramesTracking })` instead. */ enableNativeFramesTracking: boolean; /** - * Track when and how long the JS event loop stalls for. Adds stalls as measurements to all transactions. + * @deprecated Use `Sentry.init({ enableStallTracking })` instead. */ enableStallTracking: boolean; /** - * Trace User Interaction events like touch and gestures. + * @deprecated Use `Sentry.init({ enableUserInteractionTracing })` instead. */ enableUserInteractionTracing: boolean; } @@ -125,7 +128,7 @@ const defaultReactNativeTracingOptions: ReactNativeTracingOptions = { }; /** - * Tracing integration for React Native. + * @deprecated Use `Sentry.reactNativeTracingIntegration()` instead. */ export class ReactNativeTracing implements Integration { /** @@ -197,7 +200,7 @@ export class ReactNativeTracing implements Integration { getCurrentHub: () => Hub, ): Promise { const hub = getCurrentHub(); - const client = hub.getClient(); + const client = hub.getClient(); const clientOptions = client && client.getOptions(); // eslint-disable-next-line @typescript-eslint/unbound-method @@ -241,15 +244,15 @@ export class ReactNativeTracing implements Integration { ); } - if (enableAppStartTracking) { - this._instrumentAppStart().then(undefined, (reason: unknown) => { + if (clientOptions?.enableAppStartTracking ?? enableAppStartTracking) { + this._instrumentAppStart(clientOptions).then(undefined, (reason: unknown) => { logger.error(`[ReactNativeTracing] Error while instrumenting app start:`, reason); }); } - this._enableNativeFramesTracking(addGlobalEventProcessor); + this._enableNativeFramesTracking(addGlobalEventProcessor, clientOptions); - if (enableStallTracking) { + if (clientOptions?.enableStallTracking ?? enableStallTracking) { this.stallTrackingInstrumentation = new StallTrackingInstrumentation(); } @@ -321,7 +324,10 @@ export class ReactNativeTracing implements Integration { op: string; }): TransactionType | undefined { const { elementId, op } = userInteractionId; - if (!this.options.enableUserInteractionTracing) { + + const clientOptions = this._getCurrentHub?.()?.getClient()?.getOptions(); + + if (!(clientOptions?.enableUserInteractionTracing ?? this.options.enableUserInteractionTracing)) { logger.log('[ReactNativeTracing] User Interaction Tracing is disabled.'); return; } @@ -376,8 +382,13 @@ export class ReactNativeTracing implements Integration { /** * Enables or disables native frames tracking based on the `enableNativeFramesTracking` option. */ - private _enableNativeFramesTracking(addGlobalEventProcessor: (callback: EventProcessor) => void): void { - if (this.options.enableNativeFramesTracking && !NATIVE.enableNative) { + private _enableNativeFramesTracking( + addGlobalEventProcessor: (callback: EventProcessor) => void, + clientOptions: ReactNativeClientOptions | undefined, + ): void { + const enableNativeFramesTracking = + clientOptions?.enableNativeFramesTracking ?? this.options.enableNativeFramesTracking; + if (enableNativeFramesTracking && !NATIVE.enableNative) { // Do not enable native frames tracking if native is not available. logger.warn( '[ReactNativeTracing] NativeFramesTracking is not available on the Web, Expo Go and other platforms without native modules.', @@ -385,13 +396,13 @@ export class ReactNativeTracing implements Integration { return; } - if (!this.options.enableNativeFramesTracking && NATIVE.enableNative) { + if (!enableNativeFramesTracking && NATIVE.enableNative) { // Disable native frames tracking when native available and option is false. NATIVE.disableNativeFramesTracking(); return; } - if (!this.options.enableNativeFramesTracking) { + if (!enableNativeFramesTracking) { return; } @@ -433,8 +444,8 @@ export class ReactNativeTracing implements Integration { * Instruments the app start measurements on the first route transaction. * Starts a route transaction if there isn't routing instrumentation. */ - private async _instrumentAppStart(): Promise { - if (!this.options.enableAppStartTracking || !NATIVE.enableNative) { + private async _instrumentAppStart(clientOptions: ReactNativeClientOptions | undefined): Promise { + if (!(clientOptions?.enableAppStartTracking ?? this.options.enableAppStartTracking) || !NATIVE.enableNative) { return; } diff --git a/src/js/tracing/reactnavigation.ts b/src/js/tracing/reactnavigation.ts index f4225d902..4de2ee5c0 100644 --- a/src/js/tracing/reactnavigation.ts +++ b/src/js/tracing/reactnavigation.ts @@ -62,6 +62,15 @@ const defaultOptions: ReactNavigationOptions = { * - `_onStateChange` is then called AFTER the state change happens due to a dispatch and sets the route context onto the active transaction. * - If `_onStateChange` isn't called within `STATE_CHANGE_TIMEOUT_DURATION` of the dispatch, then the transaction is not sampled and finished. */ +export const reactNavigationIntegration = ( + options: Partial = {}, +): ReactNavigationInstrumentation => { + return new ReactNavigationInstrumentation(options); +}; + +/** + * @deprecated Please use `Sentry.reactNavigationIntegration()` + */ export class ReactNavigationInstrumentation extends InternalRoutingInstrumentation { public static instrumentationName: string = 'react-navigation-v5'; diff --git a/src/js/tracing/reactnavigationv4.ts b/src/js/tracing/reactnavigationv4.ts index 789375f50..c1b01e31b 100644 --- a/src/js/tracing/reactnavigationv4.ts +++ b/src/js/tracing/reactnavigationv4.ts @@ -54,6 +54,8 @@ const defaultOptions: ReactNavigationV4Options = { /** * Instrumentation for React-Navigation V4. * Register the app container with `registerAppContainer` to use, or see docs for more details. + * + * @deprecated Support for `react-navigation@4` and older will be removed in the next major version of the SDK. Please upgrade to `react-navigation@5` or newer. */ class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation { public static instrumentationName: string = 'react-navigation-v4'; diff --git a/src/js/tracing/routingInstrumentation.ts b/src/js/tracing/routingInstrumentation.ts index c7778fdcb..494db3a87 100644 --- a/src/js/tracing/routingInstrumentation.ts +++ b/src/js/tracing/routingInstrumentation.ts @@ -7,6 +7,11 @@ export type TransactionCreator = (context: TransactionContext) => Transaction | export type OnConfirmRoute = (context: TransactionContext) => void; +/** + * @deprecated Use `Integration` from `@sentry/types` and `startIdleTransaction` from `@sentry/core` instead. + * + * Or use `startIdleNavigationSpan` from `@sentry/react-native@^6`. + */ export interface RoutingInstrumentationInstance { /** * Name of the routing instrumentation @@ -36,8 +41,9 @@ export interface RoutingInstrumentationInstance { } /** - * Base Routing Instrumentation. Can be used by users to manually instrument custom routers. - * Pass this to the tracing integration, and call `onRouteWillChange` every time before a route changes. + * @deprecated Use `Integration` from `@sentry/types` and `startIdleTransaction` from `@sentry/core` instead. + * + * Or use `startIdleNavigationSpan` from `@sentry/react-native@^6`. */ export class RoutingInstrumentation implements RoutingInstrumentationInstance { public static instrumentationName: string = 'base-routing-instrumentation'; diff --git a/test/client.test.ts b/test/client.test.ts index d6eafc156..738a12766 100644 --- a/test/client.test.ts +++ b/test/client.test.ts @@ -688,6 +688,19 @@ describe('Tests ReactNativeClient', () => { expect(client.getIntegrationById('ReactNativeUserInteractionTracing')).toBeTruthy(); }); + test('register user interactions tracing root option', () => { + const client = new ReactNativeClient( + mockedOptions({ + enableUserInteractionTracing: true, + dsn: EXAMPLE_DSN, + integrations: [new ReactNativeTracing({})], + }), + ); + client.setupIntegrations(); + + expect(client.getIntegrationById('ReactNativeUserInteractionTracing')).toBeTruthy(); + }); + test('register user interactions tracing - init()', () => { const client = new ReactNativeClient( mockedOptions({ diff --git a/test/mocks/client.ts b/test/mocks/client.ts index 70864fe1f..27775834c 100644 --- a/test/mocks/client.ts +++ b/test/mocks/client.ts @@ -8,7 +8,6 @@ import { setCurrentClient, } from '@sentry/core'; import type { - ClientOptions, Event, EventHint, Integration, @@ -19,6 +18,7 @@ import type { } from '@sentry/types'; import { resolvedSyncPromise } from '@sentry/utils'; +import type { ReactNativeClientOptions } from '../../src/js/options'; import { _addTracingExtensions } from '../../src/js/tracing/addTracingExtensions'; export function getDefaultTestClientOptions(options: Partial = {}): TestClientOptions { @@ -39,14 +39,14 @@ export function getDefaultTestClientOptions(options: Partial }; } -export interface TestClientOptions extends ClientOptions { +export interface TestClientOptions extends ReactNativeClientOptions { test?: boolean; mockInstallFailure?: boolean; enableSend?: boolean; defaultIntegrations?: Integration[] | false; } -export class TestClient extends BaseClient { +export class TestClient extends BaseClient { public static instance?: TestClient; public static sendEventCalled?: (event: Event) => void; diff --git a/test/profiling/integration.test.ts b/test/profiling/integration.test.ts index b9acc58c3..2a8003c49 100644 --- a/test/profiling/integration.test.ts +++ b/test/profiling/integration.test.ts @@ -367,9 +367,7 @@ function initTestClient( const options: Sentry.ReactNativeOptions = { dsn: MOCK_DSN, enableTracing: true, - _experiments: { - profilesSampleRate: 1, - }, + profilesSampleRate: 1, integrations: integrations => { if (!testOptions.withProfiling) { return integrations.filter(i => i.name !== 'HermesProfiling'); diff --git a/test/sdk.test.ts b/test/sdk.test.ts index 7af0da5b3..0593ba166 100644 --- a/test/sdk.test.ts +++ b/test/sdk.test.ts @@ -424,6 +424,18 @@ describe('Tests the SDK functionality', () => { ); }); + it('adds profiling integration non experimental', () => { + init({ + profilesSampleRate: 0.7, + }); + + const actualOptions = usedOptions(); + const actualIntegrations = actualOptions?.integrations; + expect(actualIntegrations).toEqual( + expect.arrayContaining([expect.objectContaining({ name: 'HermesProfiling' })]), + ); + }); + it('no spotlight integration by default', () => { init({}); diff --git a/test/tracing/gesturetracing.test.ts b/test/tracing/gesturetracing.test.ts index e939b2594..8abea68b2 100644 --- a/test/tracing/gesturetracing.test.ts +++ b/test/tracing/gesturetracing.test.ts @@ -55,11 +55,12 @@ describe('GestureTracing', () => { beforeEach(() => { jest.clearAllMocks(); jest.useFakeTimers(); - client = setupTestClient(); + client = setupTestClient({ + enableUserInteractionTracing: true, + }); mockedRoutingInstrumentation = createMockedRoutingInstrumentation(); tracing = new ReactNativeTracing({ routingInstrumentation: mockedRoutingInstrumentation, - enableUserInteractionTracing: true, }); client.addIntegration(tracing); tracing.setupOnce(addGlobalEventProcessor, getCurrentHub); diff --git a/test/tracing/reactnativenavigation.test.ts b/test/tracing/reactnativenavigation.test.ts index 8bdd65e77..8ee4c5071 100644 --- a/test/tracing/reactnativenavigation.test.ts +++ b/test/tracing/reactnativenavigation.test.ts @@ -390,11 +390,11 @@ describe('React Native Navigation Instrumentation', () => { routingInstrumentation: rNavigation, enableStallTracking: false, enableNativeFramesTracking: false, - enableAppStartTracking: false, beforeNavigate: setupOptions.beforeNavigate || (span => span), }); const options = getDefaultTestClientOptions({ + enableAppStartTracking: false, tracesSampleRate: 1.0, integrations: [rnTracing], }); diff --git a/test/tracing/reactnativetracing.test.ts b/test/tracing/reactnativetracing.test.ts index 4ef365257..41aa87406 100644 --- a/test/tracing/reactnativetracing.test.ts +++ b/test/tracing/reactnativetracing.test.ts @@ -784,6 +784,21 @@ describe('ReactNativeTracing', () => { expect(NATIVE.fetchNativeAppStart).not.toBeCalled(); }); + it('Does not instrument app start if app start is disabled client option', async () => { + client = setupTestClient({ + enableAppStartTracking: false, + }); + const integration = new ReactNativeTracing({}); + setup(integration); + + await jest.advanceTimersByTimeAsync(500); + await jest.runOnlyPendingTimersAsync(); + + const transaction = client.event; + expect(transaction).toBeUndefined(); + expect(NATIVE.fetchNativeAppStart).not.toBeCalled(); + }); + it('Does not instrument app start if native is disabled', async () => { NATIVE.enableNative = false; @@ -814,11 +829,8 @@ describe('ReactNativeTracing', () => { }); describe('Native Frames', () => { - beforeEach(() => { - setupTestClient(); - }); - it('Initialize native frames instrumentation if flag is true', async () => { + setupTestClient(); const integration = new ReactNativeTracing({ enableNativeFramesTracking: true, }); @@ -830,6 +842,7 @@ describe('ReactNativeTracing', () => { expect(NATIVE.enableNativeFramesTracking).toBeCalledTimes(1); }); it('Does not initialize native frames instrumentation if flag is false', async () => { + setupTestClient(); const integration = new ReactNativeTracing({ enableNativeFramesTracking: false, }); @@ -842,6 +855,33 @@ describe('ReactNativeTracing', () => { expect(NATIVE.disableNativeFramesTracking).toBeCalledTimes(1); expect(NATIVE.fetchNativeFrames).not.toBeCalled(); }); + + it('Initialize native frames instrumentation if flag is true root option', async () => { + setupTestClient({ + enableNativeFramesTracking: true, + }); + const integration = new ReactNativeTracing({}); + setup(integration); + + await jest.advanceTimersByTimeAsync(500); + + expect(integration.nativeFramesInstrumentation).toBeDefined(); + expect(NATIVE.enableNativeFramesTracking).toBeCalledTimes(1); + }); + it('Does not initialize native frames instrumentation if flag is false root option', async () => { + setupTestClient({ + enableNativeFramesTracking: false, + }); + const integration = new ReactNativeTracing({}); + + setup(integration); + + await jest.advanceTimersByTimeAsync(500); + + expect(integration.nativeFramesInstrumentation).toBeUndefined(); + expect(NATIVE.disableNativeFramesTracking).toBeCalledTimes(1); + expect(NATIVE.fetchNativeFrames).not.toBeCalled(); + }); }); describe('Routing Instrumentation', () => { diff --git a/test/tracing/stalltracking.test.ts b/test/tracing/stalltracking.test.ts index dab30e025..d1c32f992 100644 --- a/test/tracing/stalltracking.test.ts +++ b/test/tracing/stalltracking.test.ts @@ -40,7 +40,6 @@ describe('StallTracking', () => { getGlobalScope().clear(); const rnTracing = new ReactNativeTracing({ - enableStallTracking: true, enableNativeFramesTracking: false, enableAppStartTracking: false, }); @@ -48,6 +47,7 @@ describe('StallTracking', () => { const options = getDefaultTestClientOptions({ tracesSampleRate: 1.0, integrations: [rnTracing], + enableStallTracking: true, }); client = new TestClient(options); setCurrentClient(client);