Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
- Persist fatal JS error envelopes to disk on Android before the process exits ([#6937](https://github.com/getsentry/sentry-react-native/pull/6937))
- The hard-crash envelope was only queued on the transport thread, so the event was lost when React Native terminated the process right after. It is now written to the offline cache on the calling thread and sent on the next launch, matching iOS.
- Support Expo Router 58 in `expoRouterIntegration`. Metro no longer warns about the removed `expo-router/build/global-state/router-store` module, and the integration creates navigation spans again ([#6923](https://github.com/getsentry/sentry-react-native/pull/6923))
- Start the native iOS SDK from `RNSentrySDK` when `sentry.options.json` is missing or can't be parsed and the DSN is set in `configureOptions` ([#6956](https://github.com/getsentry/sentry-react-native/pull/6956))
- The fallback options always failed to parse, so `configureOptions` never ran. Before 8.30.0 the app crashed at launch; since then the native SDK silently never started.

### Internal

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
3339C4832D6625570088EB3A /* RNSentryReplayControlTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3339C4822D6625570088EB3A /* RNSentryReplayControlTests.m */; };
336084392C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 336084382C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift */; };
3380C6C42CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3380C6C32CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift */; };
339C6C3C2D3EB25100CA72ED /* RNSentryStartTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 339C6C3B2D3EB23B00CA72ED /* RNSentryStartTests.swift */; };
339C6C422D3FD3AE00CA72ED /* RNSentryStartFromFileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 339C6C412D3FD39500CA72ED /* RNSentryStartFromFileTests.swift */; };
339C6C482D3FD9A700CA72ED /* invalid.options.json in Resources */ = {isa = PBXBuildFile; fileRef = 339C6C462D3FD91900CA72ED /* invalid.options.json */; };
339C6C492D3FD9A700CA72ED /* invalid.options.txt in Resources */ = {isa = PBXBuildFile; fileRef = 339C6C452D3FD90200CA72ED /* invalid.options.txt */; };
339C6C4B2D3FD9B200CA72ED /* valid.options.json in Resources */ = {isa = PBXBuildFile; fileRef = 339C6C4A2D3FD9AB00CA72ED /* valid.options.json */; };
33AFDFED2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 33AFDFEC2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m */; };
33AFDFF12B8D15E500AAB120 /* RNSentryDependencyContainerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 33AFDFF02B8D15E500AAB120 /* RNSentryDependencyContainerTests.m */; };
33DEDFEA2D8DBE67006066E4 /* RNSentryOnDrawReporterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33DEDFE92D8DBE5B006066E4 /* RNSentryOnDrawReporterTests.swift */; };
Expand Down Expand Up @@ -47,6 +52,11 @@
3380C6C32CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNSentryReplayPostInitTests.swift; sourceTree = "<group>"; };
338739072A7D7D2800950DDD /* RNSentryReplay.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNSentryReplay.h; path = ../ios/RNSentryReplay.h; sourceTree = "<group>"; };
33958C672BFCEF5A00AD1FB6 /* RNSentryOnDrawReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSentryOnDrawReporter.h; path = ../ios/RNSentryOnDrawReporter.h; sourceTree = "<group>"; };
339C6C3B2D3EB23B00CA72ED /* RNSentryStartTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNSentryStartTests.swift; sourceTree = "<group>"; };
339C6C412D3FD39500CA72ED /* RNSentryStartFromFileTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNSentryStartFromFileTests.swift; sourceTree = "<group>"; };
339C6C452D3FD90200CA72ED /* invalid.options.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = invalid.options.txt; sourceTree = "<group>"; };
339C6C462D3FD91900CA72ED /* invalid.options.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = invalid.options.json; sourceTree = "<group>"; };
339C6C4A2D3FD9AB00CA72ED /* valid.options.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = valid.options.json; sourceTree = "<group>"; };
33AFDFEC2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryFramesTrackerListenerTests.m; sourceTree = "<group>"; };
33AFDFF02B8D15E500AAB120 /* RNSentryDependencyContainerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryDependencyContainerTests.m; sourceTree = "<group>"; };
33AFE0132B8F31AF00AAB120 /* RNSentryDependencyContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSentryDependencyContainer.h; path = ../ios/RNSentryDependencyContainer.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -91,6 +101,7 @@
3360896929524163007C7730 = {
isa = PBXGroup;
children = (
339C6C432D3FD41C00CA72ED /* TestAssets */,
33AFE0122B8F319000AAB120 /* RNSentry */,
3360899029524164007C7730 /* RNSentryCocoaTesterTests */,
3360897329524163007C7730 /* Products */,
Expand Down Expand Up @@ -131,6 +142,8 @@
3380C6C32CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift */,
26C9B2501FF3EBD8B91BA6C1 /* RNSentryStartInvalidOptionsTests.swift */,
864F5BFD9CFDA4502ADAE72E /* RNSentrySDKStartInvalidOptionsTests.swift */,
339C6C3B2D3EB23B00CA72ED /* RNSentryStartTests.swift */,
339C6C412D3FD39500CA72ED /* RNSentryStartFromFileTests.swift */,
);
path = RNSentryCocoaTesterTests;
sourceTree = "<group>";
Expand All @@ -144,6 +157,16 @@
path = Replay;
sourceTree = "<group>";
};
339C6C432D3FD41C00CA72ED /* TestAssets */ = {
isa = PBXGroup;
children = (
339C6C4A2D3FD9AB00CA72ED /* valid.options.json */,
339C6C462D3FD91900CA72ED /* invalid.options.json */,
339C6C452D3FD90200CA72ED /* invalid.options.txt */,
);
path = TestAssets;
sourceTree = "<group>";
};
33AFE0122B8F319000AAB120 /* RNSentry */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -181,6 +204,7 @@
3360898929524164007C7730 /* Sources */,
BB7D14838753E6599863899B /* Frameworks */,
CC7959F3721CB3AD7CB6A047 /* [CP] Copy Pods Resources */,
339C6C472D3FD99900CA72ED /* Resources */,
);
buildRules = (
);
Expand Down Expand Up @@ -225,6 +249,19 @@
};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
339C6C472D3FD99900CA72ED /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
339C6C482D3FD9A700CA72ED /* invalid.options.json in Resources */,
339C6C4B2D3FD9B200CA72ED /* valid.options.json in Resources */,
339C6C492D3FD9A700CA72ED /* invalid.options.txt in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
30F19D4E16BEEFEC68733838 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
Expand Down Expand Up @@ -289,6 +326,8 @@
33AFDFED2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m in Sources */,
00C7702ED388EA0682DBCC48 /* RNSentryStartInvalidOptionsTests.swift in Sources */,
AC4EE11A6E697E75C3753C16 /* RNSentrySDKStartInvalidOptionsTests.swift in Sources */,
339C6C3C2D3EB25100CA72ED /* RNSentryStartTests.swift in Sources */,
339C6C422D3FD3AE00CA72ED /* RNSentryStartFromFileTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import XCTest

final class RNSentrySDKStartInvalidOptionsTests: XCTestCase {

// When neither the options file nor the fallback can produce options,
// the native auto-init path must not start the SDK with nil options.
// When neither the options file nor configureOptions provides a DSN,
// the native auto-init path must not start the SDK.
func testStartWithUnparseableOptionsFileDoesNotStartSdk() {
// Arrange
SentrySDK.close()

// Act — a non-existent options path forces the nil-options fallback
// Act — a non-existent options path and no configureOptions leave no DSN
RNSentrySDK.start("/does/not/exist/sentry.options.json", configureOptions: nil)

// Assert
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import XCTest

final class RNSentryStartFromFileTests: XCTestCase {

override func setUp() {
super.setUp()
SentrySDK.close()
}

func testNoThrowOnMissingOptionsFile() {
var wasConfigurationCalled = false

Expand All @@ -11,10 +16,16 @@ final class RNSentryStartFromFileTests: XCTestCase {
})

XCTAssertTrue(wasConfigurationCalled)
XCTAssertFalse(SentrySDK.isEnabled)
}

let actualOptions = SentrySDK.internal.options
XCTAssertNil(actualOptions.dsn)
XCTAssertNil(actualOptions.parsedDsn)
func testStartsWithConfigureDsnOnMissingOptionsFile() {
RNSentrySDK.start(getNonExistingOptionsPath(), configureOptions: { options in
options.dsn = "https://abcd@efgh.ingest.sentry.io/123456"
})

XCTAssertTrue(SentrySDK.isEnabled)
XCTAssertEqual(SentrySDK.internal.options.dsn, "https://abcd@efgh.ingest.sentry.io/123456")
}

func testNoThrowOnInvalidFileType() {
Expand All @@ -25,10 +36,16 @@ final class RNSentryStartFromFileTests: XCTestCase {
})

XCTAssertTrue(wasConfigurationCalled)
XCTAssertFalse(SentrySDK.isEnabled)
}

let actualOptions = SentrySDK.internal.options
XCTAssertNil(actualOptions.dsn)
XCTAssertNil(actualOptions.parsedDsn)
func testStartsWithConfigureDsnOnInvalidFileType() {
RNSentrySDK.start(getInvalidOptionsTypePath(), configureOptions: { options in
options.dsn = "https://abcd@efgh.ingest.sentry.io/123456"
})

XCTAssertTrue(SentrySDK.isEnabled)
XCTAssertEqual(SentrySDK.internal.options.dsn, "https://abcd@efgh.ingest.sentry.io/123456")
}

func testNoThrowOnInvalidOptions() {
Expand All @@ -41,7 +58,7 @@ final class RNSentryStartFromFileTests: XCTestCase {
XCTAssertTrue(wasConfigurationCalled)

let actualOptions = SentrySDK.internal.options
XCTAssertNil(actualOptions.dsn)
XCTAssertEqual(actualOptions.dsn, "https://abcd@efgh.ingest.sentry.io/123456")
XCTAssertNotNil(actualOptions.parsedDsn)
XCTAssertEqual(actualOptions.environment, "environment-from-invalid-file")
}
Expand All @@ -56,7 +73,7 @@ final class RNSentryStartFromFileTests: XCTestCase {
XCTAssertTrue(wasConfigurationCalled)

let actualOptions = SentrySDK.internal.options
XCTAssertNil(actualOptions.dsn)
XCTAssertEqual(actualOptions.dsn, "https://abcd@efgh.ingest.sentry.io/123456")
XCTAssertNotNil(actualOptions.parsedDsn)
XCTAssertEqual(actualOptions.environment, "environment-from-valid-file")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ final class RNSentryStartTests: XCTestCase {
XCTAssertFalse(actualOptions!.enableCaptureFailedRequests)
XCTAssertNil(actualOptions!.tracesSampleRate)
XCTAssertNil(actualOptions!.tracesSampler)
XCTAssertFalse(actualOptions!.enableTracing)
}

func testStartSetsReactDeafults() {
Expand Down
22 changes: 9 additions & 13 deletions packages/core/ios/RNSentrySDK.m
Original file line number Diff line number Diff line change
Expand Up @@ -59,26 +59,22 @@ + (void)start:(NSString *)path configureOptions:(void (^)(SentryOptions *options

if (options == nil) {
// Fallback in case that options file could not be parsed.
NSError *fallbackError = nil;
options = [RNSentryInternal optionsFromDictionary:@{ } error:&fallbackError];
if (fallbackError != nil) {
NSLog(@"[RNSentry] Failed to create fallback options with error: %@",
fallbackError.localizedDescription);
}
}

if (options == nil) {
// Even the fallback failed. Skip starting instead of passing nil options to
// the native SDK, which would crash it.
NSLog(@"[RNSentry] Could not create options; skipping native SDK start.");
return;
options = [[SentryOptions alloc] init];
}

[RNSentryStart updateWithReactDefaults:options];
if (configureOptions != nil) {
configureOptions(options);
}
[RNSentryStart updateWithReactFinals:options];

if (options.parsedDsn == nil) {
// Don't start without a DSN, so that a later init from JS can still start the native SDK.
NSLog(@"[RNSentry] No valid DSN in the options file or configureOptions; skipping native "
@"SDK start.");
return;
}

[RNSentryStart startWithOptions:options];
}

Expand Down
Loading