Skip to content

Commit d43a46b

Browse files
misc(deprecations): Add Tracing deprecations and replacements (#4073)
1 parent 70b4797 commit d43a46b

22 files changed

+216
-56
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@
1818
module.exports = withSentryConfig(getDefaultConfig(__dirname), { includeWebReplay: true });
1919
```
2020

21+
### Changes
22+
23+
- React Native Tracing Deprecations ([#4073](https://github.com/getsentry/sentry-react-native/pull/4073))
24+
- `new ReactNativeTracing` to `reactNativeTracingIntegration()`
25+
- `new ReactNavigationInstrumentation` to `reactNativeTracingIntegration()`.
26+
- `new ReactNativeNavigationInstrumentation` to `reactNativeTracingIntegration()`.
27+
- `ReactNavigationV4Instrumentation` won't be supported in the next major SDK version, upgrade to `react-navigation@5` or newer.
28+
- `RoutingInstrumentation` and `RoutingInstrumentationInstance` replace by `Integration` interface from `@sentry/types`.
29+
- `enableAppStartTracking`, `enableNativeFramesTracking`, `enableStallTracking`, `enableUserInteractionTracing` moved to `Sentry.init({})` root options.
30+
2131
## 5.31.1
2232

2333
### Fixes

samples/expo/app/_layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ LogBox.ignoreAllLogs();
2121
// Prevent the splash screen from auto-hiding before asset loading is complete.
2222
SplashScreen.preventAutoHideAsync();
2323

24-
const routingInstrumentation = new Sentry.ReactNavigationInstrumentation({
24+
const routingInstrumentation = Sentry.reactNavigationIntegration({
2525
enableTimeToInitialDisplay: !isExpoGo(), // This is not supported in Expo Go.
2626
});
2727

@@ -55,7 +55,7 @@ process.env.EXPO_SKIP_DURING_EXPORT !== 'true' && Sentry.init({
5555
failedRequestTargets: [/.*/],
5656
}),
5757
Sentry.metrics.metricsAggregatorIntegration(),
58-
new Sentry.ReactNativeTracing({
58+
Sentry.reactNativeTracingIntegration({
5959
routingInstrumentation,
6060
}),
6161
);

samples/react-native/src/App.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,10 @@ LogBox.ignoreAllLogs();
3838

3939
const isMobileOs = Platform.OS === 'android' || Platform.OS === 'ios';
4040

41-
const reactNavigationInstrumentation =
42-
new Sentry.ReactNavigationInstrumentation({
43-
routeChangeTimeoutMs: 500, // How long it will wait for the route change to complete. Default is 1000ms
44-
enableTimeToInitialDisplay: isMobileOs,
45-
});
41+
const reactNavigationInstrumentation = Sentry.reactNavigationIntegration({
42+
routeChangeTimeoutMs: 500, // How long it will wait for the route change to complete. Default is 1000ms
43+
enableTimeToInitialDisplay: isMobileOs,
44+
});
4645

4746
Sentry.init({
4847
// Replace the example DSN below with your own DSN:
@@ -64,13 +63,13 @@ Sentry.init({
6463
didCallNativeInit,
6564
);
6665
},
66+
enableUserInteractionTracing: true,
6767
integrations(integrations) {
6868
integrations.push(
69-
new Sentry.ReactNativeTracing({
69+
Sentry.reactNativeTracingIntegration({
7070
// The time to wait in ms until the transaction will be finished, For testing, default is 1000 ms
7171
idleTimeout: 5000,
7272
routingInstrumentation: reactNavigationInstrumentation,
73-
enableUserInteractionTracing: true,
7473
ignoreEmptyBackNavigationTransactions: true,
7574
beforeNavigate: (context: Sentry.ReactNavigationTransactionContext) => {
7675
// Example of not sending a transaction for the screen with the name "Manual Tracker"

src/js/client.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ export class ReactNativeClient extends BaseClient<ReactNativeClientOptions> {
129129
if (routingName) {
130130
this.addIntegration(createIntegration(routingName));
131131
}
132-
const enableUserInteractionTracing = tracing?.options.enableUserInteractionTracing;
132+
const enableUserInteractionTracing =
133+
this._options.enableUserInteractionTracing ?? tracing?.options.enableUserInteractionTracing;
133134
if (enableUserInteractionTracing) {
134135
this.addIntegration(createIntegration('ReactNativeUserInteractionTracing'));
135136
}

src/js/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,13 @@ export { TouchEventBoundary, withTouchEventBoundary } from './touchevents';
9191
export {
9292
ReactNativeTracing,
9393
ReactNavigationV4Instrumentation,
94-
// eslint-disable-next-line deprecation/deprecation
9594
ReactNavigationV5Instrumentation,
9695
ReactNavigationInstrumentation,
9796
ReactNativeNavigationInstrumentation,
9897
RoutingInstrumentation,
98+
reactNativeTracingIntegration,
99+
reactNavigationIntegration,
100+
reactNativeNavigationIntegration,
99101
sentryTraceGesture,
100102
TimeToInitialDisplay,
101103
TimeToFullDisplay,

src/js/integrations/default.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ export function getDefaultIntegrations(options: ReactNativeClientOptions): Integ
8585
if (options.attachViewHierarchy) {
8686
integrations.push(viewHierarchyIntegration());
8787
}
88-
if (options._experiments && typeof options._experiments.profilesSampleRate === 'number') {
88+
if (
89+
options.profilesSampleRate ??
90+
(options._experiments && typeof options._experiments.profilesSampleRate === 'number')
91+
) {
8992
integrations.push(hermesProfilingIntegration());
9093
}
9194
}

src/js/options.ts

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,15 +204,52 @@ export interface BaseReactNativeOptions {
204204
*/
205205
beforeScreenshot?: (event: Event, hint: EventHint) => boolean;
206206

207+
/**
208+
* The sample rate for profiling
209+
* 1.0 will profile all transactions and 0 will profile none.
210+
*/
211+
profilesSampleRate?: number;
212+
213+
/**
214+
* Track the app start time by adding measurements to the first route transaction. If there is no routing instrumentation
215+
* an app start transaction will be started.
216+
*
217+
* Requires performance monitoring to be enabled.
218+
*
219+
* @default true
220+
*/
221+
enableAppStartTracking?: boolean;
222+
223+
/**
224+
* Track the slow and frozen frames in the application. Enabling this options will add
225+
* slow and frozen frames measurements to all created root spans (transactions).
226+
*
227+
* @default true
228+
*/
229+
enableNativeFramesTracking?: boolean;
230+
231+
/**
232+
* Track when and how long the JS event loop stalls for. Adds stalls as measurements to all transactions.
233+
*
234+
* @default true
235+
*/
236+
enableStallTracking?: boolean;
237+
238+
/**
239+
* Trace User Interaction events like touch and gestures.
240+
*
241+
* @default false
242+
*/
243+
enableUserInteractionTracing?: boolean;
244+
207245
/**
208246
* Options which are in beta, or otherwise not guaranteed to be stable.
209247
*/
210248
_experiments?: {
211249
[key: string]: unknown;
212250

213251
/**
214-
* The sample rate for profiling
215-
* 1.0 will profile all transactions and 0 will profile none.
252+
* @deprecated Use `profilesSampleRate` in the options root instead.
216253
*/
217254
profilesSampleRate?: number;
218255

src/js/profiling/integration.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
import { logger, uuid4 } from '@sentry/utils';
1313
import { Platform } from 'react-native';
1414

15+
import type { ReactNativeClient } from '../client';
1516
import { isHermesEnabled } from '../utils/environment';
1617
import { NATIVE } from '../wrapper';
1718
import { PROFILE_QUEUE } from './cache';
@@ -109,13 +110,16 @@ export const hermesProfilingIntegration: IntegrationFn = () => {
109110
return false;
110111
}
111112

112-
const client = getClient();
113+
const client = getClient<ReactNativeClient>();
113114
const options = client && client.getOptions();
114115

115116
const profilesSampleRate =
116-
options && options._experiments && typeof options._experiments.profilesSampleRate === 'number'
117-
? options._experiments.profilesSampleRate
118-
: undefined;
117+
options &&
118+
((typeof options.profilesSampleRate === 'number' && options.profilesSampleRate) ||
119+
(options._experiments &&
120+
typeof options._experiments.profilesSampleRate === 'number' &&
121+
options._experiments.profilesSampleRate) ||
122+
undefined);
119123
if (profilesSampleRate === undefined) {
120124
logger.log('[Profiling] Profiling disabled, enable it by setting `profilesSampleRate` option to SDK init call.');
121125
return false;

src/js/tracing/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
export { ReactNativeTracing } from './reactnativetracing';
1+
export { ReactNativeTracing, reactNativeTracingIntegration } from './reactnativetracing';
22

33
export type { RoutingInstrumentationInstance } from './routingInstrumentation';
44
export { RoutingInstrumentation } from './routingInstrumentation';
55

66
export {
77
ReactNavigationInstrumentation,
8+
reactNavigationIntegration,
89
// eslint-disable-next-line deprecation/deprecation
910
ReactNavigationV5Instrumentation,
1011
} from './reactnavigation';
1112
export { ReactNavigationV4Instrumentation } from './reactnavigationv4';
12-
export { ReactNativeNavigationInstrumentation } from './reactnativenavigation';
13+
export { ReactNativeNavigationInstrumentation, reactNativeNavigationIntegration } from './reactnativenavigation';
1314

1415
export type { ReactNavigationCurrentRoute, ReactNavigationRoute, ReactNavigationTransactionContext } from './types';
1516

src/js/tracing/reactnativenavigation.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ export interface NavigationDelegate {
6868
* - `_onComponentWillAppear` is then called AFTER the state change happens due to a dispatch and sets the route context onto the active transaction.
6969
* - If `_onComponentWillAppear` isn't called within `options.routeChangeTimeoutMs` of the dispatch, then the transaction is not sampled and finished.
7070
*/
71+
export const reactNativeNavigationIntegration = (
72+
options: Partial<ReactNativeNavigationOptions> & {
73+
navigation: NavigationDelegate;
74+
},
75+
): ReactNativeNavigationInstrumentation => {
76+
return new ReactNativeNavigationInstrumentation(options.navigation, options);
77+
};
78+
79+
/**
80+
* @deprecated Use `Sentry.reactNativeNavigationIntegration({ navigation })` instead.
81+
*/
7182
export class ReactNativeNavigationInstrumentation extends InternalRoutingInstrumentation {
7283
public static instrumentationName: string = 'react-native-navigation';
7384

src/js/tracing/reactnativetracing.ts

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ import type {
1313
} from '@sentry/types';
1414
import { logger } from '@sentry/utils';
1515

16+
import type { ReactNativeClient } from '../client';
1617
import { APP_START_COLD, APP_START_WARM } from '../measurements';
1718
import type { NativeAppStartResponse } from '../NativeRNSentry';
19+
import type { ReactNativeClientOptions } from '../options';
1820
import type { RoutingInstrumentationInstance } from '../tracing/routingInstrumentation';
1921
import { NATIVE } from '../wrapper';
2022
import { NativeFramesInstrumentation } from './nativeframes';
@@ -30,6 +32,10 @@ import {
3032
setSpanDurationAsMeasurement,
3133
} from './utils';
3234

35+
export const reactNativeTracingIntegration = (options?: Partial<ReactNativeTracingOptions>): ReactNativeTracing => {
36+
return new ReactNativeTracing(options);
37+
};
38+
3339
export interface ReactNativeTracingOptions extends RequestInstrumentationOptions {
3440
/**
3541
* @deprecated Replaced by idleTimeoutMs
@@ -85,25 +91,22 @@ export interface ReactNativeTracingOptions extends RequestInstrumentationOptions
8591
beforeNavigate: BeforeNavigate;
8692

8793
/**
88-
* Track the app start time by adding measurements to the first route transaction. If there is no routing instrumentation
89-
* an app start transaction will be started.
90-
*
91-
* Default: true
94+
* @deprecated Use `Sentry.init({ enableAppStartTracking })` instead.
9295
*/
9396
enableAppStartTracking: boolean;
9497

9598
/**
96-
* Track slow/frozen frames from the native layer and adds them as measurements to all transactions.
99+
* @deprecated Use `Sentry.init({ enableNativeFramesTracking })` instead.
97100
*/
98101
enableNativeFramesTracking: boolean;
99102

100103
/**
101-
* Track when and how long the JS event loop stalls for. Adds stalls as measurements to all transactions.
104+
* @deprecated Use `Sentry.init({ enableStallTracking })` instead.
102105
*/
103106
enableStallTracking: boolean;
104107

105108
/**
106-
* Trace User Interaction events like touch and gestures.
109+
* @deprecated Use `Sentry.init({ enableUserInteractionTracing })` instead.
107110
*/
108111
enableUserInteractionTracing: boolean;
109112
}
@@ -125,7 +128,7 @@ const defaultReactNativeTracingOptions: ReactNativeTracingOptions = {
125128
};
126129

127130
/**
128-
* Tracing integration for React Native.
131+
* @deprecated Use `Sentry.reactNativeTracingIntegration()` instead.
129132
*/
130133
export class ReactNativeTracing implements Integration {
131134
/**
@@ -197,7 +200,7 @@ export class ReactNativeTracing implements Integration {
197200
getCurrentHub: () => Hub,
198201
): Promise<void> {
199202
const hub = getCurrentHub();
200-
const client = hub.getClient();
203+
const client = hub.getClient<ReactNativeClient>();
201204
const clientOptions = client && client.getOptions();
202205

203206
// eslint-disable-next-line @typescript-eslint/unbound-method
@@ -241,15 +244,15 @@ export class ReactNativeTracing implements Integration {
241244
);
242245
}
243246

244-
if (enableAppStartTracking) {
245-
this._instrumentAppStart().then(undefined, (reason: unknown) => {
247+
if (clientOptions?.enableAppStartTracking ?? enableAppStartTracking) {
248+
this._instrumentAppStart(clientOptions).then(undefined, (reason: unknown) => {
246249
logger.error(`[ReactNativeTracing] Error while instrumenting app start:`, reason);
247250
});
248251
}
249252

250-
this._enableNativeFramesTracking(addGlobalEventProcessor);
253+
this._enableNativeFramesTracking(addGlobalEventProcessor, clientOptions);
251254

252-
if (enableStallTracking) {
255+
if (clientOptions?.enableStallTracking ?? enableStallTracking) {
253256
this.stallTrackingInstrumentation = new StallTrackingInstrumentation();
254257
}
255258

@@ -321,7 +324,10 @@ export class ReactNativeTracing implements Integration {
321324
op: string;
322325
}): TransactionType | undefined {
323326
const { elementId, op } = userInteractionId;
324-
if (!this.options.enableUserInteractionTracing) {
327+
328+
const clientOptions = this._getCurrentHub?.()?.getClient<ReactNativeClient>()?.getOptions();
329+
330+
if (!(clientOptions?.enableUserInteractionTracing ?? this.options.enableUserInteractionTracing)) {
325331
logger.log('[ReactNativeTracing] User Interaction Tracing is disabled.');
326332
return;
327333
}
@@ -376,22 +382,27 @@ export class ReactNativeTracing implements Integration {
376382
/**
377383
* Enables or disables native frames tracking based on the `enableNativeFramesTracking` option.
378384
*/
379-
private _enableNativeFramesTracking(addGlobalEventProcessor: (callback: EventProcessor) => void): void {
380-
if (this.options.enableNativeFramesTracking && !NATIVE.enableNative) {
385+
private _enableNativeFramesTracking(
386+
addGlobalEventProcessor: (callback: EventProcessor) => void,
387+
clientOptions: ReactNativeClientOptions | undefined,
388+
): void {
389+
const enableNativeFramesTracking =
390+
clientOptions?.enableNativeFramesTracking ?? this.options.enableNativeFramesTracking;
391+
if (enableNativeFramesTracking && !NATIVE.enableNative) {
381392
// Do not enable native frames tracking if native is not available.
382393
logger.warn(
383394
'[ReactNativeTracing] NativeFramesTracking is not available on the Web, Expo Go and other platforms without native modules.',
384395
);
385396
return;
386397
}
387398

388-
if (!this.options.enableNativeFramesTracking && NATIVE.enableNative) {
399+
if (!enableNativeFramesTracking && NATIVE.enableNative) {
389400
// Disable native frames tracking when native available and option is false.
390401
NATIVE.disableNativeFramesTracking();
391402
return;
392403
}
393404

394-
if (!this.options.enableNativeFramesTracking) {
405+
if (!enableNativeFramesTracking) {
395406
return;
396407
}
397408

@@ -433,8 +444,8 @@ export class ReactNativeTracing implements Integration {
433444
* Instruments the app start measurements on the first route transaction.
434445
* Starts a route transaction if there isn't routing instrumentation.
435446
*/
436-
private async _instrumentAppStart(): Promise<void> {
437-
if (!this.options.enableAppStartTracking || !NATIVE.enableNative) {
447+
private async _instrumentAppStart(clientOptions: ReactNativeClientOptions | undefined): Promise<void> {
448+
if (!(clientOptions?.enableAppStartTracking ?? this.options.enableAppStartTracking) || !NATIVE.enableNative) {
438449
return;
439450
}
440451

src/js/tracing/reactnavigation.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ const defaultOptions: ReactNavigationOptions = {
6262
* - `_onStateChange` is then called AFTER the state change happens due to a dispatch and sets the route context onto the active transaction.
6363
* - If `_onStateChange` isn't called within `STATE_CHANGE_TIMEOUT_DURATION` of the dispatch, then the transaction is not sampled and finished.
6464
*/
65+
export const reactNavigationIntegration = (
66+
options: Partial<ReactNavigationOptions> = {},
67+
): ReactNavigationInstrumentation => {
68+
return new ReactNavigationInstrumentation(options);
69+
};
70+
71+
/**
72+
* @deprecated Please use `Sentry.reactNavigationIntegration()`
73+
*/
6574
export class ReactNavigationInstrumentation extends InternalRoutingInstrumentation {
6675
public static instrumentationName: string = 'react-navigation-v5';
6776

src/js/tracing/reactnavigationv4.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ const defaultOptions: ReactNavigationV4Options = {
5454
/**
5555
* Instrumentation for React-Navigation V4.
5656
* Register the app container with `registerAppContainer` to use, or see docs for more details.
57+
*
58+
* @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.
5759
*/
5860
class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation {
5961
public static instrumentationName: string = 'react-navigation-v4';

0 commit comments

Comments
 (0)