Skip to content

Commit 8a54dff

Browse files
Merge 1528fb5 into 834729f
2 parents 834729f + 1528fb5 commit 8a54dff

File tree

70 files changed

+1035
-389
lines changed

Some content is hidden

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

70 files changed

+1035
-389
lines changed

CHANGELOG.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,63 @@
22

33
<!-- prettier-ignore-start -->
44
> [!IMPORTANT]
5-
> If you are upgrading to the `6.x` versions of the Sentry React Native SDK from `5.x` or below,
5+
> If you are upgrading to the `7.x` versions of the Sentry React Native SDK from `6.x` or below,
66
> make sure you follow our [migration guide](https://docs.sentry.io/platforms/react-native/migration/) first.
77
<!-- prettier-ignore-end -->
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 based on the Sentry Javascript SDK version 9. 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
### Fixes
1218

1319
- Expo Updates Context is passed to native after native init to be available for crashes ([#4808](https://github.com/getsentry/sentry-react-native/pull/4808))
1420
- Expo Updates Context values should all be lowercase ([#4809](https://github.com/getsentry/sentry-react-native/pull/4809))
1521

22+
### Major Changes
23+
24+
- Set `{{auto}}` if `user.ip_address` is `undefined` and `sendDefaultPii: true` ([#4466](https://github.com/getsentry/sentry-react-native/pull/4466))
25+
- Exceptions from `captureConsoleIntegration` are now marked as handled: true by default
26+
- `shutdownTimeout` moved from `core` to `@sentry/react-native`
27+
- `hasTracingEnabled` was renamed to `hasSpansEnabled`
28+
- You can no longer drop spans or return null on `beforeSendSpan` hook
29+
30+
### Removed types
31+
32+
- TransactionNamingScheme
33+
- Request
34+
- Scope (prefer using the Scope class)
35+
36+
### Other removed items.
37+
38+
- `autoSessionTracking` from options.
39+
To enable session tracking, ensure that `enableAutoSessionTracking` is enabled.
40+
- `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.
41+
- `getCurrentHub()`, `Hub`, and `getCurrentHubShim()`
42+
- `spanId` from propagation `context`
43+
- metrics API
44+
- `transactionContext` from `samplingContext`
45+
- `@sentry/utils` package, the exports were moved to `@sentry/core`
46+
- Standalone `Client` interface & deprecate `BaseClient`
47+
48+
## Other Changes
49+
50+
- Fork `scope` if custom scope is passed to `startSpanManual` or `startSpan`
51+
- On React Native Web, `browserSessionIntegration` is added when `enableAutoSessionTracking` is set to `True` ([#4732](https://github.com/getsentry/sentry-react-native/pull/4732))
52+
Change `Cold/Warm App Start` span description to `Cold/Warm Start` ([#4636](https://github.com/getsentry/sentry-react-native/pull/4636))
53+
1654
### Dependencies
1755

56+
- Bump JavaScript SDK from v8.54.0 to v9.12.0 ([#4568](https://github.com/getsentry/sentry-react-native/pull/4568), [#4752](https://github.com/getsentry/sentry-react-native/pull/4752))
57+
- [changelog](https://github.com/getsentry/sentry-javascript/blob/9.12.0/CHANGELOG.md)
58+
- [diff](https://github.com/getsentry/sentry-javascript/compare/8.54.0...9.12.0)
59+
- Bump Android SDK from v7.20.1 to v8.11.1 ([#4490](https://github.com/getsentry/sentry-react-native/pull/4490))
60+
- [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#8111)
61+
- [diff](https://github.com/getsentry/sentry-java/compare/7.20.1...8.11.1)
1862
- Bump CLI from v2.43.1 to v2.45.0 ([#4804](https://github.com/getsentry/sentry-react-native/pull/4804), [#4818](https://github.com/getsentry/sentry-react-native/pull/4818))
1963
- [changelog](https://github.com/getsentry/sentry-cli/blob/master/CHANGELOG.md#2450)
2064
- [diff](https://github.com/getsentry/sentry-cli/compare/2.43.1...2.45.0)

dev-packages/e2e-tests/package.json

Lines changed: 1 addition & 1 deletion
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.12.0",
1717
"@sentry/react-native": "6.13.1",
1818
"@types/node": "^20.9.3",
1919
"@types/react": "^18.2.64",

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

Lines changed: 4 additions & 0 deletions
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,8 @@ declare global {
1921
redirectCount: number;
2022
}
2123
interface PerformanceEntry {}
24+
interface Performance {}
25+
interface PerformanceNavigationTiming {}
2226
}
2327

2428
declare module 'react-native' {

packages/core/android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,5 @@ android {
5454

5555
dependencies {
5656
implementation 'com.facebook.react:react-native:+'
57-
api 'io.sentry:sentry-android:7.22.5'
57+
api 'io.sentry:sentry-android:8.11.1'
5858
}

packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@
3030
import com.facebook.react.bridge.WritableNativeMap;
3131
import com.facebook.react.common.JavascriptException;
3232
import io.sentry.Breadcrumb;
33-
import io.sentry.HubAdapter;
3433
import io.sentry.ILogger;
3534
import io.sentry.IScope;
3635
import io.sentry.ISentryExecutorService;
3736
import io.sentry.ISerializer;
3837
import io.sentry.Integration;
38+
import io.sentry.ScopesAdapter;
3939
import io.sentry.Sentry;
4040
import io.sentry.SentryDate;
4141
import io.sentry.SentryDateProvider;
@@ -87,6 +87,7 @@
8787
import java.util.List;
8888
import java.util.Map;
8989
import java.util.Properties;
90+
import java.util.Set;
9091
import java.util.concurrent.CountDownLatch;
9192
import org.jetbrains.annotations.NotNull;
9293
import org.jetbrains.annotations.Nullable;
@@ -527,7 +528,7 @@ public void fetchNativeFrames(Promise promise) {
527528
}
528529

529530
public void captureReplay(boolean isHardCrash, Promise promise) {
530-
Sentry.getCurrentHub().getOptions().getReplayController().captureReplay(isHardCrash);
531+
Sentry.getCurrentScopes().getOptions().getReplayController().captureReplay(isHardCrash);
531532
promise.resolve(getCurrentReplayId());
532533
}
533534

@@ -623,7 +624,7 @@ public void fetchViewHierarchy(Promise promise) {
623624
return;
624625
}
625626

626-
ISerializer serializer = HubAdapter.getInstance().getOptions().getSerializer();
627+
ISerializer serializer = ScopesAdapter.getInstance().getOptions().getSerializer();
627628
final @Nullable byte[] bytes =
628629
JsonSerializationUtils.bytesFrom(serializer, logger, viewHierarchy);
629630
if (bytes == null) {
@@ -677,10 +678,6 @@ public void setUser(final ReadableMap userKeys, final ReadableMap userDataKeys)
677678
if (userKeys.hasKey("ip_address")) {
678679
userInstance.setIpAddress(userKeys.getString("ip_address"));
679680
}
680-
681-
if (userKeys.hasKey("segment")) {
682-
userInstance.setSegment(userKeys.getString("segment"));
683-
}
684681
}
685682

686683
if (userDataKeys != null) {
@@ -842,8 +839,7 @@ private void initializeAndroidProfiler() {
842839
(int) SECONDS.toMicros(1) / profilingTracesHz,
843840
new SentryFrameMetricsCollector(reactApplicationContext, logger, buildInfo),
844841
executorService,
845-
logger,
846-
buildInfo);
842+
logger);
847843
}
848844

849845
public WritableMap startProfiling(boolean platformProfilers) {
@@ -867,7 +863,7 @@ public WritableMap startProfiling(boolean platformProfilers) {
867863
}
868864

869865
public WritableMap stopProfiling() {
870-
final boolean isDebug = HubAdapter.getInstance().getOptions().isDebug();
866+
final boolean isDebug = ScopesAdapter.getInstance().getOptions().isDebug();
871867
final WritableMap result = new WritableNativeMap();
872868
File output = null;
873869
try {
@@ -953,7 +949,7 @@ private String readStringFromFile(File path) throws IOException {
953949
}
954950

955951
public void fetchNativeDeviceContexts(Promise promise) {
956-
final @NotNull SentryOptions options = HubAdapter.getInstance().getOptions();
952+
final @NotNull SentryOptions options = ScopesAdapter.getInstance().getOptions();
957953
final @Nullable Context context = this.getReactApplicationContext().getApplicationContext();
958954
final @Nullable IScope currentScope = InternalSentrySdk.getCurrentScope();
959955
fetchNativeDeviceContexts(promise, options, context, currentScope);
@@ -990,7 +986,8 @@ protected void fetchNativeDeviceContexts(
990986
}
991987

992988
public void fetchNativeSdkInfo(Promise promise) {
993-
final @Nullable SdkVersion sdkVersion = HubAdapter.getInstance().getOptions().getSdkVersion();
989+
final @Nullable SdkVersion sdkVersion =
990+
ScopesAdapter.getInstance().getOptions().getSdkVersion();
994991
if (sdkVersion == null) {
995992
promise.resolve(null);
996993
} else {
@@ -1069,14 +1066,14 @@ private void addPackages(SentryEvent event, SdkVersion sdk) {
10691066
if (eventSdk != null
10701067
&& "sentry.javascript.react-native".equals(eventSdk.getName())
10711068
&& sdk != null) {
1072-
List<SentryPackage> sentryPackages = sdk.getPackages();
1069+
Set<SentryPackage> sentryPackages = sdk.getPackageSet();
10731070
if (sentryPackages != null) {
10741071
for (SentryPackage sentryPackage : sentryPackages) {
10751072
eventSdk.addPackage(sentryPackage.getName(), sentryPackage.getVersion());
10761073
}
10771074
}
10781075

1079-
List<String> integrations = sdk.getIntegrations();
1076+
Set<String> integrations = sdk.getIntegrationSet();
10801077
if (integrations != null) {
10811078
for (String integration : integrations) {
10821079
eventSdk.addIntegration(integration);

packages/core/package.json

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,21 +66,20 @@
6666
},
6767
"dependencies": {
6868
"@sentry/babel-plugin-component-annotate": "3.4.0",
69-
"@sentry/browser": "8.54.0",
70-
"@sentry/cli": "2.45.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"
69+
"@sentry/browser": "9.12.0",
70+
"@sentry/cli": "2.43.0",
71+
"@sentry/core": "9.12.0",
72+
"@sentry/react": "9.12.0",
73+
"@sentry/types": "9.12.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.12.0",
81+
"@sentry-internal/eslint-plugin-sdk": "9.12.0",
82+
"@sentry-internal/typescript": "9.12.0",
8483
"@sentry/wizard": "4.9.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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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/client.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@ import type {
1010
TransportMakeRequestResponse,
1111
UserFeedback,
1212
} from '@sentry/core';
13-
import { BaseClient, dateTimestampInSeconds, logger, SentryError } from '@sentry/core';
13+
import {
14+
addAutoIpAddressToSession,
15+
addAutoIpAddressToUser,
16+
BaseClient,
17+
dateTimestampInSeconds,
18+
logger,
19+
SentryError,
20+
} from '@sentry/core';
1421
import { Alert } from 'react-native';
1522

1623
import { getDevServer } from './integrations/debugsymbolicatorutils';
@@ -48,6 +55,11 @@ export class ReactNativeClient extends BaseClient<ReactNativeClientOptions> {
4855
super(options);
4956

5057
this._outcomesBuffer = [];
58+
59+
if (options.sendDefaultPii === true) {
60+
this.on('postprocessEvent', addAutoIpAddressToUser);
61+
this.on('beforeSendSession', addAutoIpAddressToSession);
62+
}
5163
}
5264

5365
/**

packages/core/src/js/feedback/FeedbackWidget.tsx

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ import { base64ToUint8Array, feedbackAlertDialog, isValidEmail } from './utils'
2626
* Implements a feedback form screen that sends feedback to Sentry using Sentry.captureFeedback.
2727
*/
2828
export class FeedbackWidget extends React.Component<FeedbackWidgetProps, FeedbackWidgetState> {
29-
public static defaultProps: Partial<FeedbackWidgetProps> = {
30-
...defaultConfiguration
31-
}
29+
public static defaultProps = defaultConfiguration;
3230

3331
private static _savedState: Omit<FeedbackWidgetState, 'isVisible'> = {
3432
name: '',
@@ -67,7 +65,7 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
6765
public handleFeedbackSubmit: () => void = () => {
6866
const { name, email, description } = this.state;
6967
const { onSubmitSuccess, onSubmitError, onFormSubmitted } = this.props;
70-
const text: FeedbackTextConfiguration = this.props;
68+
const text = this.props;
7169

7270
const trimmedName = name?.trim();
7371
const trimmedEmail = email?.trim();
@@ -119,14 +117,14 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
119117

120118
public onScreenshotButtonPress: () => void = async () => {
121119
if (!this.state.filename && !this.state.attachment) {
122-
const imagePickerConfiguration: ImagePickerConfiguration = this.props;
123-
if (imagePickerConfiguration.imagePicker) {
124-
const launchImageLibrary = imagePickerConfiguration.imagePicker.launchImageLibraryAsync
120+
const { imagePicker } = this.props;
121+
if (imagePicker) {
122+
const launchImageLibrary = imagePicker.launchImageLibraryAsync
125123
// expo-image-picker library is available
126-
? () => imagePickerConfiguration.imagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], base64: isWeb() })
124+
? () => imagePicker.launchImageLibraryAsync?.({ mediaTypes: ['images'], base64: isWeb() })
127125
// react-native-image-picker library is available
128-
: imagePickerConfiguration.imagePicker.launchImageLibrary
129-
? () => imagePickerConfiguration.imagePicker.launchImageLibrary({ mediaType: 'photo', includeBase64: isWeb() })
126+
: imagePicker.launchImageLibrary
127+
? () => imagePicker.launchImageLibrary?.({ mediaType: 'photo', includeBase64: isWeb() })
130128
: null;
131129
if (!launchImageLibrary) {
132130
logger.warn('No compatible image picker library found. Please provide a valid image picker library.');
@@ -140,22 +138,22 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
140138
}
141139

142140
const result = await launchImageLibrary();
143-
if (result.assets && result.assets.length > 0) {
141+
if (result?.assets && result.assets.length > 0) {
144142
if (isWeb()) {
145-
const filename = result.assets[0].fileName;
146-
const imageUri = result.assets[0].uri;
147-
const base64 = result.assets[0].base64;
148-
const data = base64ToUint8Array(base64);
149-
if (data != null) {
143+
const filename = result.assets[0]?.fileName;
144+
const imageUri = result.assets[0]?.uri;
145+
const base64 = result.assets[0]?.base64;
146+
const data = base64 ? base64ToUint8Array(base64) : undefined;
147+
if (data) {
150148
this.setState({ filename, attachment: data, attachmentUri: imageUri });
151149
} else {
152150
logger.error('Failed to read image data on the web');
153151
}
154152
} else {
155-
const filename = result.assets[0].fileName;
156-
const imageUri = result.assets[0].uri;
157-
getDataFromUri(imageUri).then((data) => {
158-
if (data != null) {
153+
const filename = result.assets[0]?.fileName;
154+
const imageUri = result.assets[0]?.uri;
155+
imageUri && getDataFromUri(imageUri).then((data) => {
156+
if (data) {
159157
this.setState({ filename, attachment: data, attachmentUri: imageUri });
160158
} else {
161159
logger.error('Failed to read image data from uri:', imageUri);

0 commit comments

Comments
 (0)