Skip to content

Commit 6eaf70f

Browse files
feat: Bump to Sentry Javascript V9 (#4568)
* bump SDKs * bump SDKs * fix build * fix tests * fix tests * fix lint errors * test ts 5.0 * rollback * fix merge conflict with yarn * fix new lint issue * sync yarn.lock with V7 branch and install new packages * ensure we are using the JS version from the default node resolution * update changelog with javascript version bump * fix check type (#4587) * add major changes to the SDK * fix lint * review check: fix changelog PR number / Fix wrapper incorrect null check / removed comment from rnerror handler / removed comment from span / fix test from userInteraction * fix incorrect cli version * fix lint * remove shutdowntimeout from android / use newer wizard version * rollback feedback test change, rollback jest version, fix safe test * return shutdowntimeout * explain tracing sample rate * fix tracing extension test * lint fix * update changelog * fix yarn lock merge/ fix ts-jest version no longer exists / fix core version on samples and e2e * fix lint on addTimeToInitialDisplay * fix issue with UIManager test * moved major changes to the correct spot
1 parent 077a1bd commit 6eaf70f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+319
-228
lines changed

CHANGELOG.md

+42
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
99
## Unreleased
1010

11+
### Upgrading from 6.x to 7.0
12+
13+
Version 7 of the Sentry React Native SDK primarily introduces API cleanup and version support changes. This update contains behavioral changes that will not be caught by type checkers, linters, or tests, so we recommend carefully reading through the entire migration guide instead of relying on automatic tooling.
14+
15+
Version 7 of the SDK is compatible with Sentry self-hosted versions 24.4.2 or higher (unchanged from v6). Lower versions may continue to work, but may not support all features.
16+
1117
### Dependencies
1218

1319
- Bump Bundler Plugins from v3.2.2 to v3.2.4 ([#4693](https://github.com/getsentry/sentry-react-native/pull/4693), [#4707](https://github.com/getsentry/sentry-react-native/pull/4707))
@@ -17,6 +23,39 @@
1723
- [changelog](https://github.com/getsentry/sentry-cli/blob/master/CHANGELOG.md#2430)
1824
- [diff](https://github.com/getsentry/sentry-cli/compare/2.42.4...2.43.0)
1925

26+
### Major Changes
27+
28+
- `ip addresses` is only collected when `sendDefaultPii`: `true`
29+
- Exceptions from `captureConsoleIntegration` are now marked as handled: true by default
30+
- `shutdownTimeout` moved from `core` to `@sentry/react-native`
31+
- `hasTracingEnabled` was renamed to `hasSpansEnabled`
32+
- You can no longer drop spans or return null on `beforeSendSpan` hook
33+
34+
### Removed types
35+
36+
- TransactionNamingScheme
37+
- Request
38+
- Scope (prefer using the Scope class)
39+
40+
### Other removed items.
41+
42+
- `autoSessionTracking` from options.
43+
To enable session tracking, ensure that `enableAutoSessionTracking` is enabled.
44+
45+
- `enableTracing`. Instead, set `tracesSampleRate` to a value greater than `zero` to `enable tracing`, `0` to keep tracing integrations active without sampling, or `undefined` to disable the performance integration.
46+
47+
- `getCurrentHub()`, `Hub`, and `getCurrentHubShim()`
48+
- `spanId` from propagation `context`
49+
- metrics API
50+
- `transactionContext` from `samplingContext`
51+
- `@sentry/utils` package, the exports were moved to `@sentry/core`
52+
- Standalone `Client` interface & deprecate `BaseClient`
53+
54+
## Other Changes
55+
56+
- Fork `scope` if custom scope is passed to `startSpanManual` or `startSpan`
57+
58+
2059
## 6.11.0-beta.0
2160

2261
### Features
@@ -186,6 +225,9 @@ Change `Cold/Warm App Start` span description to `Cold/Warm Start` ([#4636](http
186225

187226
### Dependencies
188227

228+
- Bump JavaScript SDK from v8.54.0 to v9.1.0 ([#4568](https://github.com/getsentry/sentry-react-native/pull/4568))
229+
- [changelog](https://github.com/getsentry/sentry-javascript/blob/9.1.0/CHANGELOG.md)
230+
- [diff](https://github.com/getsentry/sentry-javascript/compare/8.54.0...9.1.0)
189231
- Bump Android SDK from v7.20.1 to v8.3.0 ([#4490](https://github.com/getsentry/sentry-react-native/pull/4490))
190232
- [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#830)
191233
- [diff](https://github.com/getsentry/sentry-java/compare/7.20.1...8.3.0)

dev-packages/e2e-tests/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"devDependencies": {
1414
"@babel/preset-env": "^7.25.3",
1515
"@babel/preset-typescript": "^7.18.6",
16-
"@sentry/core": "8.54.0",
16+
"@sentry/core": "9.1.0",
1717
"@sentry/react-native": "6.11.0-beta.0",
1818
"@types/node": "^20.9.3",
1919
"@types/react": "^18.2.64",

dev-packages/type-check/ts3.8-test/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ declare global {
33
interface IDBObjectStore {}
44
interface Window {
55
fetch: any;
6+
setTimeout: any;
7+
document: any;
68
}
79
interface ShadowRoot {}
810
interface BufferSource {}
@@ -19,6 +21,7 @@ declare global {
1921
redirectCount: number;
2022
}
2123
interface PerformanceEntry {}
24+
interface Performance {}
2225
}
2326

2427
declare module 'react-native' {

packages/core/package.json

+9-10
Original file line numberDiff line numberDiff line change
@@ -65,22 +65,21 @@
6565
"react-native": ">=0.65.0"
6666
},
6767
"dependencies": {
68-
"@sentry/babel-plugin-component-annotate": "3.2.4",
69-
"@sentry/browser": "8.54.0",
68+
"@sentry/babel-plugin-component-annotate": "3.1.2",
69+
"@sentry/browser": "9.1.0",
7070
"@sentry/cli": "2.43.0",
71-
"@sentry/core": "8.54.0",
72-
"@sentry/react": "8.54.0",
73-
"@sentry/types": "8.54.0",
74-
"@sentry/utils": "8.54.0"
71+
"@sentry/core": "9.1.0",
72+
"@sentry/react": "9.1.0",
73+
"@sentry/types": "9.1.0"
7574
},
7675
"devDependencies": {
7776
"@babel/core": "^7.25.2",
7877
"@expo/metro-config": "0.19.5",
7978
"@mswjs/interceptors": "^0.25.15",
8079
"@react-native/babel-preset": "0.77.1",
81-
"@sentry-internal/eslint-config-sdk": "8.54.0",
82-
"@sentry-internal/eslint-plugin-sdk": "8.54.0",
83-
"@sentry-internal/typescript": "8.54.0",
80+
"@sentry-internal/eslint-config-sdk": "9.1.0",
81+
"@sentry-internal/eslint-plugin-sdk": "9.1.0",
82+
"@sentry-internal/typescript": "9.1.0",
8483
"@sentry/wizard": "4.6.0",
8584
"@testing-library/react-native": "^12.7.2",
8685
"@types/jest": "^29.5.13",
@@ -110,7 +109,7 @@
110109
"react-native": "0.77.1",
111110
"react-test-renderer": "^18.3.1",
112111
"rimraf": "^4.1.1",
113-
"ts-jest": "^29.1.1",
112+
"ts-jest": "^29.3.1",
114113
"typescript": "4.9.5",
115114
"uglify-js": "^3.17.4",
116115
"uuid": "^9.0.1",

packages/core/plugin/src/withSentry.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ interface PluginProps {
1818
const withSentryPlugin: ConfigPlugin<PluginProps | void> = (config, props) => {
1919
const sentryProperties = getSentryProperties(props);
2020

21-
if (props && props.authToken) {
21+
if (props?.authToken) {
2222
// If not removed, the plugin config with the authToken will be written to the application package
2323
delete props.authToken;
2424
}

packages/core/plugin/src/withSentryAndroidGradlePlugin.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function withSentryAndroidGradlePlugin(
3535
const withSentryProjectBuildGradle = (config: any): any => {
3636
return withProjectBuildGradle(config, (projectBuildGradle: any) => {
3737
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
38-
if (!projectBuildGradle.modResults || !projectBuildGradle.modResults.contents) {
38+
if (!projectBuildGradle.modResults?.contents) {
3939
warnOnce('android/build.gradle content is missing or undefined.');
4040
return config;
4141
}

packages/core/src/js/index.ts

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
export type {
22
Breadcrumb,
3-
Request,
43
SdkInfo,
54
Event,
65
Exception,
@@ -43,7 +42,6 @@ export {
4342
getClient,
4443
setCurrentClient,
4544
addEventProcessor,
46-
metricsDefault as metrics,
4745
lastEventId,
4846
} from '@sentry/core';
4947

packages/core/src/js/integrations/debugsymbolicator.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ function replaceExceptionFramesInException(exception: Exception, frames: SentryS
143143
* @param frames StackFrame[]
144144
*/
145145
function replaceThreadFramesInEvent(event: Event, frames: SentryStackFrame[]): void {
146-
if (event.threads && event.threads.values && event.threads.values[0] && event.threads.values[0].stacktrace) {
146+
if (event.threads?.values?.[0]?.stacktrace) {
147147
event.threads.values[0].stacktrace.frames = frames.reverse();
148148
}
149149
}

packages/core/src/js/integrations/default.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,7 @@ export function getDefaultIntegrations(options: ReactNativeClientOptions): Integ
9393
// hasTracingEnabled from `@sentry/core` only check if tracesSampler or tracesSampleRate keys are present
9494
// that's different from prev imp here and might lead misconfiguration
9595
// `tracesSampleRate: undefined` should not enable tracing
96-
const hasTracingEnabled =
97-
options.enableTracing ||
98-
typeof options.tracesSampleRate === 'number' ||
99-
typeof options.tracesSampler === 'function';
96+
const hasTracingEnabled = typeof options.tracesSampleRate === 'number' || typeof options.tracesSampler === 'function';
10097
if (hasTracingEnabled && options.enableAppStartTracking) {
10198
integrations.push(appStartIntegration());
10299
}

packages/core/src/js/integrations/nativelinkederrors.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export const nativeLinkedErrorsIntegration = (options: Partial<LinkedErrorsOptio
4343
};
4444

4545
function preprocessEvent(event: Event, hint: EventHint | undefined, client: Client, limit: number, key: string): void {
46-
if (!event.exception || !event.exception.values || !hint || !isInstanceOf(hint.originalException, Error)) {
46+
if (!event.exception?.values || !hint || !isInstanceOf(hint.originalException, Error)) {
4747
return;
4848
}
4949

@@ -176,10 +176,10 @@ function exceptionFromAppleStackReturnAddresses(objCException: {
176176
type: objCException.name,
177177
value: objCException.message,
178178
stacktrace: {
179-
frames: (nativeStackFrames && nativeStackFrames.frames.reverse()) || [],
179+
frames: nativeStackFrames?.frames.reverse() || [],
180180
},
181181
},
182-
appleDebugImages: (nativeStackFrames && (nativeStackFrames.debugMetaImages as DebugImage[])) || [],
182+
appleDebugImages: (nativeStackFrames?.debugMetaImages as DebugImage[]) || [],
183183
};
184184
}
185185

packages/core/src/js/integrations/reactnativeerrorhandlers.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { EventHint, Integration, SeverityLevel } from '@sentry/core';
22
import { addExceptionMechanism, captureException, getClient, getCurrentScope, logger } from '@sentry/core';
33

4+
import type { ReactNativeClientOptions } from '../options';
45
import { createSyntheticError, isErrorLike } from '../utils/error';
56
import { RN_GLOBAL_OBJ } from '../utils/worldwide';
67
import { checkPromiseAndWarn, polyfillPromise, requireRejectionTracking } from './reactnativeerrorhandlersutils';
@@ -99,7 +100,7 @@ function setupErrorUtilsGlobalHandler(): void {
99100
return;
100101
}
101102

102-
const defaultHandler = errorUtils.getGlobalHandler && errorUtils.getGlobalHandler();
103+
const defaultHandler = errorUtils.getGlobalHandler?.();
103104

104105
// eslint-disable-next-line @typescript-eslint/no-explicit-any
105106
errorUtils.setGlobalHandler(async (error: any, isFatal?: boolean) => {
@@ -155,7 +156,7 @@ function setupErrorUtilsGlobalHandler(): void {
155156
return;
156157
}
157158

158-
void client.flush(client.getOptions().shutdownTimeout || 2000).then(
159+
void client.flush((client.getOptions() as ReactNativeClientOptions).shutdownTimeout || 2000).then(
159160
() => {
160161
defaultHandler(error, isFatal);
161162
},

packages/core/src/js/integrations/screenshot.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ export const screenshotIntegration = (): Integration => {
1818
};
1919

2020
async function processEvent(event: Event, hint: EventHint, client: ReactNativeClient): Promise<Event> {
21-
const hasException = event.exception && event.exception.values && event.exception.values.length > 0;
21+
const hasException = event.exception?.values?.length > 0;
2222
if (!hasException || client.getOptions().beforeScreenshot?.(event, hint) === false) {
2323
return event;
2424
}
2525

2626
const screenshots: ScreenshotAttachment[] | null = await NATIVE.captureScreenshot();
27-
if (screenshots && screenshots.length > 0) {
27+
if (screenshots?.length > 0) {
2828
hint.attachments = [...screenshots, ...(hint?.attachments || [])];
2929
}
3030

packages/core/src/js/integrations/spotlight.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ function getHostnameFromString(urlString: string): string | null {
103103
const regex = /^(?:\w+:)?\/\/([^/:]+)(:\d+)?(.*)$/;
104104
const matches = urlString.match(regex);
105105

106-
if (matches && matches[1]) {
106+
if (matches?.[1]) {
107107
return matches[1];
108108
} else {
109109
// Invalid URL format

packages/core/src/js/integrations/viewhierarchy.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export const viewHierarchyIntegration = (): Integration => {
2121
};
2222

2323
async function processEvent(event: Event, hint: EventHint): Promise<Event> {
24-
const hasException = event.exception && event.exception.values && event.exception.values.length > 0;
24+
const hasException = event.exception?.values?.length > 0;
2525
if (!hasException) {
2626
return event;
2727
}

packages/core/src/js/options.ts

+8
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,14 @@ export interface BaseReactNativeOptions {
234234
*/
235235
replaysOnErrorSampleRate?: number;
236236

237+
/**
238+
* Controls how many milliseconds to wait before shutting down. The default is 2 seconds. Setting this too low can cause
239+
* problems for sending events from command line applications. Setting it too
240+
* high can cause the application to block for users with network connectivity
241+
* problems.
242+
*/
243+
shutdownTimeout?: number;
244+
237245
/**
238246
* Options which are in beta, or otherwise not guaranteed to be stable.
239247
*/

packages/core/src/js/profiling/convertHermesProfile.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ function mapStacks(
163163
while (currentHermesFrameId !== undefined) {
164164
const sentryFrameId = hermesStackFrameIdToSentryFrameIdMap.get(currentHermesFrameId);
165165
sentryFrameId !== undefined && stack.push(sentryFrameId);
166-
currentHermesFrameId = hermesStackFrames[currentHermesFrameId] && hermesStackFrames[currentHermesFrameId].parent;
166+
currentHermesFrameId = hermesStackFrames[currentHermesFrameId]?.parent;
167167
}
168168
stacks.push(stack);
169169
}

packages/core/src/js/profiling/integration.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export const hermesProfilingIntegration = (initOptions: HermesProfilingOptions =
128128
}
129129

130130
const client = getClient<ReactNativeClient>();
131-
const options = client && client.getOptions();
131+
const options = client?.getOptions?.();
132132

133133
const profilesSampleRate =
134134
options && typeof options.profilesSampleRate === 'number' ? options.profilesSampleRate : undefined;

packages/core/src/js/profiling/utils.ts

+20-24
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ export function enrichCombinedProfileWithEventContext(
7575
return null;
7676
}
7777

78-
const trace_id = (event.contexts && event.contexts.trace && event.contexts.trace.trace_id) || '';
78+
const trace_id = event.contexts?.trace?.trace_id || '';
7979

8080
// Log a warning if the profile has an invalid traceId (should be uuidv4).
8181
// All profiles and transactions are rejected if this is the case and we want to
8282
// warn users that this is happening if they enable debug flag
83-
if (trace_id && trace_id.length !== 32) {
83+
if (trace_id?.length !== 32) {
8484
if (__DEV__) {
8585
logger.log(`[Profiling] Invalid traceId: ${trace_id} on profiled event`);
8686
}
@@ -97,25 +97,25 @@ export function enrichCombinedProfileWithEventContext(
9797
release: event.release || '',
9898
environment: event.environment || getDefaultEnvironment(),
9999
os: {
100-
name: (event.contexts && event.contexts.os && event.contexts.os.name) || '',
101-
version: (event.contexts && event.contexts.os && event.contexts.os.version) || '',
102-
build_number: (event.contexts && event.contexts.os && event.contexts.os.build) || '',
100+
name: event.contexts?.os?.name || '',
101+
version: event.contexts?.os?.version || '',
102+
build_number: event.contexts?.os?.build || '',
103103
},
104104
device: {
105-
locale: (event.contexts && event.contexts.device && (event.contexts.device.locale as string)) || '',
106-
model: (event.contexts && event.contexts.device && event.contexts.device.model) || '',
107-
manufacturer: (event.contexts && event.contexts.device && event.contexts.device.manufacturer) || '',
108-
architecture: (event.contexts && event.contexts.device && event.contexts.device.arch) || '',
109-
is_emulator: (event.contexts && event.contexts.device && event.contexts.device.simulator) || false,
105+
locale: (event.contexts?.device && (event.contexts.device.locale as string)) || '',
106+
model: event.contexts?.device?.model || '',
107+
manufacturer: event.contexts?.device?.manufacturer || '',
108+
architecture: event.contexts?.device?.arch || '',
109+
is_emulator: event.contexts?.device?.simulator || false,
110110
},
111111
transaction: {
112112
name: event.transaction || '',
113113
id: event.event_id || '',
114114
trace_id,
115-
active_thread_id: (profile.transaction && profile.transaction.active_thread_id) || '',
115+
active_thread_id: profile.transaction?.active_thread_id || '',
116116
},
117117
debug_meta: {
118-
images: [...getDebugMetadata(), ...((profile.debug_meta && profile.debug_meta.images) || [])],
118+
images: [...getDebugMetadata(), ...(profile.debug_meta?.images || [])],
119119
},
120120
};
121121
}
@@ -136,19 +136,15 @@ export function enrichAndroidProfileWithEventContext(
136136
build_id: profile.build_id || '',
137137

138138
device_cpu_frequencies: [],
139-
device_is_emulator: (event.contexts && event.contexts.device && event.contexts.device.simulator) || false,
140-
device_locale: (event.contexts && event.contexts.device && (event.contexts.device.locale as string)) || '',
141-
device_manufacturer: (event.contexts && event.contexts.device && event.contexts.device.manufacturer) || '',
142-
device_model: (event.contexts && event.contexts.device && event.contexts.device.model) || '',
143-
device_os_name: (event.contexts && event.contexts.os && event.contexts.os.name) || '',
144-
device_os_version: (event.contexts && event.contexts.os && event.contexts.os.version) || '',
139+
device_is_emulator: event.contexts?.device?.simulator || false,
140+
device_locale: (event.contexts?.device && (event.contexts.device.locale as string)) || '',
141+
device_manufacturer: event.contexts?.device?.manufacturer || '',
142+
device_model: event.contexts?.device?.model || '',
143+
device_os_name: event.contexts?.os?.name || '',
144+
device_os_version: event.contexts?.os?.version || '',
145145

146146
device_physical_memory_bytes:
147-
(event.contexts &&
148-
event.contexts.device &&
149-
event.contexts.device.memory_size &&
150-
Number(event.contexts.device.memory_size).toString(10)) ||
151-
'',
147+
(event.contexts?.device?.memory_size && Number(event.contexts.device.memory_size).toString(10)) || '',
152148

153149
environment: event.environment || getDefaultEnvironment(),
154150

@@ -161,7 +157,7 @@ export function enrichAndroidProfileWithEventContext(
161157

162158
transaction_id: event.event_id || '',
163159
transaction_name: event.transaction || '',
164-
trace_id: (event.contexts && event.contexts.trace && event.contexts.trace.trace_id) || '',
160+
trace_id: event.contexts?.trace?.trace_id || '',
165161

166162
version_name: event.release || '',
167163
version_code: event.dist || '',

packages/core/src/js/replay/CustomMask.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const UnmaskFallback = (viewProps: ViewProps): React.ReactElement => {
3434
return <View {...viewProps} />;
3535
};
3636

37-
const hasViewManagerConfig = (nativeComponentName: string): boolean => UIManager.hasViewManagerConfig && UIManager.hasViewManagerConfig(nativeComponentName);
37+
const hasViewManagerConfig = (nativeComponentName: string): boolean => UIManager.hasViewManagerConfig?.(nativeComponentName);
3838

3939
const Mask = ((): HostComponent<ViewProps> | React.ComponentType<ViewProps> => {
4040
if (isExpoGo() || !hasViewManagerConfig(MaskNativeComponentName)) {

0 commit comments

Comments
 (0)