Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 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 @@ -10,6 +10,7 @@

### Fixes

- Add mechanism field to unhandled rejection errors ([#4457](https://github.com/getsentry/sentry-react-native/pull/4457))
- Use proper SDK name for Session Replay tags ([#4428](https://github.com/getsentry/sentry-react-native/pull/4428))
- Use `makeDsn` from `core` to extract the URL from DSN avoiding unimplemented `URL.protocol` errors ([#4395](https://github.com/getsentry/sentry-react-native/pull/4395))

Expand All @@ -21,6 +22,7 @@
### Internal

- Initialize `RNSentryTimeToDisplay` during native module `init` on iOS ([#4443](https://github.com/getsentry/sentry-react-native/pull/4443))
- Extract iOS native initialization to standalone structures ([#4442](https://github.com/getsentry/sentry-react-native/pull/4442))

### Dependencies

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
332D33482CDBDC7300547D76 /* RNSentry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNSentry.h; path = ../ios/RNSentry.h; sourceTree = SOURCE_ROOT; };
332D33492CDCC8E100547D76 /* RNSentryTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNSentryTests.h; sourceTree = "<group>"; };
332D334A2CDCC8EB00547D76 /* RNSentryCocoaTesterTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNSentryCocoaTesterTests-Bridging-Header.h"; sourceTree = "<group>"; };
333B58A82D35BA93000F8D04 /* RNSentryStart.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNSentryStart.h; path = ../ios/RNSentryStart.h; sourceTree = SOURCE_ROOT; };
333B58A92D35BB2D000F8D04 /* RNSentryStart+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "RNSentryStart+Test.h"; path = "RNSentryCocoaTesterTests/RNSentryStart+Test.h"; sourceTree = SOURCE_ROOT; };
336084382C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RNSentryReplayBreadcrumbConverterTests.swift; sourceTree = "<group>"; };
3360843A2C32E3A8008CC412 /* RNSentryReplayBreadcrumbConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSentryReplayBreadcrumbConverter.h; path = ../ios/RNSentryReplayBreadcrumbConverter.h; sourceTree = "<group>"; };
3360843C2C340C76008CC412 /* RNSentryBreadcrumbTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNSentryBreadcrumbTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -116,6 +118,8 @@
33AFE0122B8F319000AAB120 /* RNSentry */ = {
isa = PBXGroup;
children = (
333B58A92D35BB2D000F8D04 /* RNSentryStart+Test.h */,
333B58A82D35BA93000F8D04 /* RNSentryStart.h */,
3380C6C02CDEC56B0018B9B6 /* Replay */,
332D33482CDBDC7300547D76 /* RNSentry.h */,
3360843A2C32E3A8008CC412 /* RNSentryReplayBreadcrumbConverter.h */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#import "RNSentryStart.h"

@interface
RNSentryStart (Test)

+ (void)setEventOriginTag:(SentryEvent *)event;

@end

Large diffs are not rendered by default.

5 changes: 0 additions & 5 deletions packages/core/ios/RNSentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ SentrySDK (Private)

@interface RNSentry : RCTEventEmitter <RCTBridgeModule>

- (SentryOptions *_Nullable)createOptionsWithDictionary:(NSDictionary *_Nonnull)options
error:(NSError *_Nullable *_Nonnull)errorPointer;

- (void)setEventOriginTag:(SentryEvent *)event;

- (NSDictionary *_Nonnull)fetchNativeStackFramesBy:(NSArray<NSNumber *> *)instructionsAddr
symbolicate:(SymbolicateCallbackType)symbolicate;

Expand Down
171 changes: 3 additions & 168 deletions packages/core/ios/RNSentry.mm
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
# import "RNSentryRNSScreen.h"
#endif

#import "RNSentryStart.h"
#import "RNSentryVersion.h"

@interface
Expand All @@ -63,7 +64,6 @@ + (void)storeEnvelope:(SentryEnvelope *)envelope;
static bool hasFetchedAppStart;

@implementation RNSentry {
bool sentHybridSdkDidBecomeActive;
bool hasListeners;
RNSentryTimeToDisplay *_timeToDisplay;
}
Expand Down Expand Up @@ -94,181 +94,16 @@ - (instancetype)init
: (RCTPromiseRejectBlock)reject)
{
NSError *error = nil;
SentryOptions *sentryOptions = [self createOptionsWithDictionary:options error:&error];
SentryOptions *sentryOptions = [RNSentryStart createOptionsWithDictionary:options error:&error];
if (error != nil) {
reject(@"SentryReactNative", error.localizedDescription, error);
return;
}

NSString *sdkVersion = [PrivateSentrySDKOnly getSdkVersionString];
[PrivateSentrySDKOnly setSdkName:NATIVE_SDK_NAME andVersionString:sdkVersion];
[PrivateSentrySDKOnly addSdkPackage:REACT_NATIVE_SDK_PACKAGE_NAME
version:REACT_NATIVE_SDK_PACKAGE_VERSION];

[SentrySDK startWithOptions:sentryOptions];

#if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST
BOOL appIsActive =
[[UIApplication sharedApplication] applicationState] == UIApplicationStateActive;
#else
BOOL appIsActive = [[NSApplication sharedApplication] isActive];
#endif

// If the app is active/in foreground, and we have not sent the SentryHybridSdkDidBecomeActive
// notification, send it.
if (appIsActive && !sentHybridSdkDidBecomeActive
&& (PrivateSentrySDKOnly.options.enableAutoSessionTracking
|| PrivateSentrySDKOnly.options.enableWatchdogTerminationTracking)) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"SentryHybridSdkDidBecomeActive"
object:nil];

sentHybridSdkDidBecomeActive = true;
}

#if SENTRY_TARGET_REPLAY_SUPPORTED
[RNSentryReplay postInit];
#endif

[RNSentryStart startWithOptions:sentryOptions];
resolve(@YES);
}

- (SentryOptions *_Nullable)createOptionsWithDictionary:(NSDictionary *_Nonnull)options
error:(NSError *_Nonnull *_Nonnull)errorPointer
{
SentryBeforeSendEventCallback beforeSend = ^SentryEvent *(SentryEvent *event)
{
// We don't want to send an event after startup that came from a Unhandled JS Exception of
// react native Because we sent it already before the app crashed.
if (nil != event.exceptions.firstObject.type &&
[event.exceptions.firstObject.type rangeOfString:@"Unhandled JS Exception"].location
!= NSNotFound) {
return nil;
}

[self setEventOriginTag:event];

return event;
};

NSMutableDictionary *mutableOptions = [options mutableCopy];
[mutableOptions setValue:beforeSend forKey:@"beforeSend"];

// remove performance traces sample rate and traces sampler since we don't want to synchronize
// these configurations to the Native SDKs. The user could tho initialize the SDK manually and
// set themselves.
[mutableOptions removeObjectForKey:@"tracesSampleRate"];
[mutableOptions removeObjectForKey:@"tracesSampler"];
[mutableOptions removeObjectForKey:@"enableTracing"];

#if SENTRY_TARGET_REPLAY_SUPPORTED
[RNSentryReplay updateOptions:mutableOptions];
#endif

SentryOptions *sentryOptions = [[SentryOptions alloc] initWithDict:mutableOptions
didFailWithError:errorPointer];
if (*errorPointer != nil) {
return nil;
}

// Exclude Dev Server and Sentry Dsn request from Breadcrumbs
NSString *dsn = [self getURLFromDSN:[mutableOptions valueForKey:@"dsn"]];
NSString *devServerUrl = [mutableOptions valueForKey:@"devServerUrl"];
sentryOptions.beforeBreadcrumb
= ^SentryBreadcrumb *_Nullable(SentryBreadcrumb *_Nonnull breadcrumb)
{
NSString *url = breadcrumb.data[@"url"] ?: @"";

if ([@"http" isEqualToString:breadcrumb.type]
&& ((dsn != nil && [url hasPrefix:dsn])
|| (devServerUrl != nil && [url hasPrefix:devServerUrl]))) {
return nil;
}
return breadcrumb;
};

if ([mutableOptions valueForKey:@"enableNativeCrashHandling"] != nil) {
BOOL enableNativeCrashHandling = [mutableOptions[@"enableNativeCrashHandling"] boolValue];

if (!enableNativeCrashHandling) {
NSMutableArray *integrations = sentryOptions.integrations.mutableCopy;
[integrations removeObject:@"SentryCrashIntegration"];
sentryOptions.integrations = integrations;
}
}

// Set spotlight option
if ([mutableOptions valueForKey:@"spotlight"] != nil) {
id spotlightValue = [mutableOptions valueForKey:@"spotlight"];
if ([spotlightValue isKindOfClass:[NSString class]]) {
NSLog(@"Using Spotlight on address: %@", spotlightValue);
sentryOptions.enableSpotlight = true;
sentryOptions.spotlightUrl = spotlightValue;
} else if ([spotlightValue isKindOfClass:[NSNumber class]]) {
sentryOptions.enableSpotlight = [spotlightValue boolValue];
id defaultSpotlightUrl = [mutableOptions valueForKey:@"defaultSidecarUrl"];
if (defaultSpotlightUrl != nil) {
sentryOptions.spotlightUrl = defaultSpotlightUrl;
}
}
}

// Enable the App start and Frames tracking measurements
if ([mutableOptions valueForKey:@"enableAutoPerformanceTracing"] != nil) {
BOOL enableAutoPerformanceTracing =
[mutableOptions[@"enableAutoPerformanceTracing"] boolValue];
PrivateSentrySDKOnly.appStartMeasurementHybridSDKMode = enableAutoPerformanceTracing;
#if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST
PrivateSentrySDKOnly.framesTrackingMeasurementHybridSDKMode = enableAutoPerformanceTracing;
#endif
}

// Failed requests can only be enabled in one SDK to avoid duplicates
sentryOptions.enableCaptureFailedRequests = NO;

return sentryOptions;
}

- (NSString *_Nullable)getURLFromDSN:(NSString *)dsn
{
NSURL *url = [NSURL URLWithString:dsn];
if (!url) {
return nil;
}
return [NSString stringWithFormat:@"%@://%@", url.scheme, url.host];
}

- (void)setEventOriginTag:(SentryEvent *)event
{
if (event.sdk != nil) {
NSString *sdkName = event.sdk[@"name"];

// If the event is from react native, it gets set
// there and we do not handle it here.
if ([sdkName isEqual:NATIVE_SDK_NAME]) {
[self setEventEnvironmentTag:event origin:@"ios" environment:@"native"];
}
}
}

- (void)setEventEnvironmentTag:(SentryEvent *)event
origin:(NSString *)origin
environment:(NSString *)environment
{
NSMutableDictionary *newTags = [NSMutableDictionary new];

if (nil != event.tags && [event.tags count] > 0) {
[newTags addEntriesFromDictionary:event.tags];
}
if (nil != origin) {
[newTags setValue:origin forKey:@"event.origin"];
}
if (nil != environment) {
[newTags setValue:environment forKey:@"event.environment"];
}

event.tags = newTags;
}

RCT_EXPORT_METHOD(initNativeReactNavigationNewFrameTracking
: (RCTPromiseResolveBlock)resolve rejecter
: (RCTPromiseRejectBlock)reject)
Expand Down
20 changes: 20 additions & 0 deletions packages/core/ios/RNSentryStart.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#import <Sentry/SentryDefines.h>
#import <Sentry/SentryOptions.h>

@interface RNSentryStart : NSObject
SENTRY_NO_INIT

+ (SentryOptions *_Nullable)createOptionsWithDictionary:(NSDictionary *_Nonnull)options
error:(NSError *_Nonnull *_Nonnull)errorPointer;

/**
* @experimental
* Inits and configures Sentry for React Native applications. Make sure to
* set a valid DSN.
*
* @discussion Call this method on the main thread. When calling it from a background thread, the
* SDK starts on the main thread async.
*/
+ (void)startWithOptions:(SentryOptions *)options NS_SWIFT_NAME(start(options:));

@end
Loading
Loading