@sentry/react-native 6.5.0 → 6.7.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/RNSentry.podspec +2 -2
- package/android/build.gradle +1 -1
- package/android/src/main/java/io/sentry/react/RNSentryCompositeOptionsConfiguration.java +25 -0
- package/android/src/main/java/io/sentry/react/RNSentryJsonConverter.java +76 -0
- package/android/src/main/java/io/sentry/react/RNSentryJsonUtils.java +41 -0
- package/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java +2 -280
- package/android/src/main/java/io/sentry/react/RNSentrySDK.java +68 -0
- package/android/src/main/java/io/sentry/react/RNSentryStart.java +365 -0
- package/android/src/main/java/io/sentry/react/RNSentryVersion.java +2 -1
- package/dist/js/integrations/reactnativeerrorhandlers.js +1 -0
- package/dist/js/integrations/reactnativeerrorhandlers.js.map +1 -1
- package/dist/js/sdk.d.ts.map +1 -1
- package/dist/js/sdk.js +27 -17
- package/dist/js/sdk.js.map +1 -1
- package/dist/js/tools/metroconfig.d.ts +9 -1
- package/dist/js/tools/metroconfig.d.ts.map +1 -1
- package/dist/js/tools/metroconfig.js +9 -2
- package/dist/js/tools/metroconfig.js.map +1 -1
- package/dist/js/tools/sentryMetroSerializer.d.ts.map +1 -1
- package/dist/js/tools/sentryMetroSerializer.js +1 -0
- package/dist/js/tools/sentryMetroSerializer.js.map +1 -1
- package/dist/js/tools/sentryOptionsSerializer.d.ts +6 -0
- package/dist/js/tools/sentryOptionsSerializer.d.ts.map +1 -0
- package/dist/js/tools/sentryOptionsSerializer.js +91 -0
- package/dist/js/tools/sentryOptionsSerializer.js.map +1 -0
- package/dist/js/tools/utils.d.ts +2 -1
- package/dist/js/tools/utils.d.ts.map +1 -1
- package/dist/js/tools/utils.js.map +1 -1
- package/dist/js/tracing/reactnavigation.js +2 -2
- package/dist/js/tracing/reactnavigation.js.map +1 -1
- package/dist/js/utils/worldwide.d.ts +2 -0
- package/dist/js/utils/worldwide.d.ts.map +1 -1
- package/dist/js/utils/worldwide.js.map +1 -1
- package/dist/js/version.d.ts +1 -1
- package/dist/js/version.d.ts.map +1 -1
- package/dist/js/version.js +1 -1
- package/dist/js/version.js.map +1 -1
- package/ios/RNSentry.h +3 -5
- package/ios/RNSentry.mm +12 -171
- package/ios/RNSentryReplay.mm +3 -0
- package/ios/RNSentrySDK.h +31 -0
- package/ios/RNSentrySDK.m +71 -0
- package/ios/RNSentryStart.h +26 -0
- package/ios/RNSentryStart.m +222 -0
- package/ios/RNSentryVersion.h +6 -0
- package/ios/RNSentryVersion.m +6 -0
- package/package.json +11 -11
- package/scripts/sentry-xcode.sh +19 -0
- package/sentry.gradle +52 -1
- package/ts3.8/dist/js/utils/worldwide.d.ts +2 -0
- package/ts3.8/dist/js/version.d.ts +1 -1
package/ios/RNSentry.mm
CHANGED
|
@@ -49,6 +49,9 @@
|
|
|
49
49
|
# import "RNSentryRNSScreen.h"
|
|
50
50
|
#endif
|
|
51
51
|
|
|
52
|
+
#import "RNSentryStart.h"
|
|
53
|
+
#import "RNSentryVersion.h"
|
|
54
|
+
|
|
52
55
|
@interface
|
|
53
56
|
SentrySDK (RNSentry)
|
|
54
57
|
|
|
@@ -60,10 +63,7 @@ SentrySDK (RNSentry)
|
|
|
60
63
|
|
|
61
64
|
static bool hasFetchedAppStart;
|
|
62
65
|
|
|
63
|
-
static NSString *const nativeSdkName = @"sentry.cocoa.react-native";
|
|
64
|
-
|
|
65
66
|
@implementation RNSentry {
|
|
66
|
-
bool sentHybridSdkDidBecomeActive;
|
|
67
67
|
bool hasListeners;
|
|
68
68
|
RNSentryTimeToDisplay *_timeToDisplay;
|
|
69
69
|
}
|
|
@@ -78,6 +78,14 @@ static NSString *const nativeSdkName = @"sentry.cocoa.react-native";
|
|
|
78
78
|
return YES;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
- (instancetype)init
|
|
82
|
+
{
|
|
83
|
+
if (self = [super init]) {
|
|
84
|
+
_timeToDisplay = [[RNSentryTimeToDisplay alloc] init];
|
|
85
|
+
}
|
|
86
|
+
return self;
|
|
87
|
+
}
|
|
88
|
+
|
|
81
89
|
RCT_EXPORT_MODULE()
|
|
82
90
|
|
|
83
91
|
RCT_EXPORT_METHOD(initNativeSdk
|
|
@@ -86,181 +94,14 @@ RCT_EXPORT_METHOD(initNativeSdk
|
|
|
86
94
|
: (RCTPromiseRejectBlock)reject)
|
|
87
95
|
{
|
|
88
96
|
NSError *error = nil;
|
|
89
|
-
|
|
97
|
+
[RNSentryStart startWithOptions:options error:&error];
|
|
90
98
|
if (error != nil) {
|
|
91
99
|
reject(@"SentryReactNative", error.localizedDescription, error);
|
|
92
100
|
return;
|
|
93
101
|
}
|
|
94
|
-
|
|
95
|
-
NSString *sdkVersion = [PrivateSentrySDKOnly getSdkVersionString];
|
|
96
|
-
[PrivateSentrySDKOnly setSdkName:nativeSdkName andVersionString:sdkVersion];
|
|
97
|
-
|
|
98
|
-
[SentrySDK startWithOptions:sentryOptions];
|
|
99
|
-
|
|
100
|
-
#if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST
|
|
101
|
-
BOOL appIsActive =
|
|
102
|
-
[[UIApplication sharedApplication] applicationState] == UIApplicationStateActive;
|
|
103
|
-
#else
|
|
104
|
-
BOOL appIsActive = [[NSApplication sharedApplication] isActive];
|
|
105
|
-
#endif
|
|
106
|
-
|
|
107
|
-
// If the app is active/in foreground, and we have not sent the SentryHybridSdkDidBecomeActive
|
|
108
|
-
// notification, send it.
|
|
109
|
-
if (appIsActive && !sentHybridSdkDidBecomeActive
|
|
110
|
-
&& (PrivateSentrySDKOnly.options.enableAutoSessionTracking
|
|
111
|
-
|| PrivateSentrySDKOnly.options.enableWatchdogTerminationTracking)) {
|
|
112
|
-
[[NSNotificationCenter defaultCenter] postNotificationName:@"SentryHybridSdkDidBecomeActive"
|
|
113
|
-
object:nil];
|
|
114
|
-
|
|
115
|
-
sentHybridSdkDidBecomeActive = true;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
#if SENTRY_TARGET_REPLAY_SUPPORTED
|
|
119
|
-
[RNSentryReplay postInit];
|
|
120
|
-
#endif
|
|
121
|
-
|
|
122
102
|
resolve(@YES);
|
|
123
103
|
}
|
|
124
104
|
|
|
125
|
-
- (SentryOptions *_Nullable)createOptionsWithDictionary:(NSDictionary *_Nonnull)options
|
|
126
|
-
error:(NSError *_Nonnull *_Nonnull)errorPointer
|
|
127
|
-
{
|
|
128
|
-
SentryBeforeSendEventCallback beforeSend = ^SentryEvent *(SentryEvent *event)
|
|
129
|
-
{
|
|
130
|
-
// We don't want to send an event after startup that came from a Unhandled JS Exception of
|
|
131
|
-
// react native Because we sent it already before the app crashed.
|
|
132
|
-
if (nil != event.exceptions.firstObject.type &&
|
|
133
|
-
[event.exceptions.firstObject.type rangeOfString:@"Unhandled JS Exception"].location
|
|
134
|
-
!= NSNotFound) {
|
|
135
|
-
return nil;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
[self setEventOriginTag:event];
|
|
139
|
-
|
|
140
|
-
return event;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
NSMutableDictionary *mutableOptions = [options mutableCopy];
|
|
144
|
-
[mutableOptions setValue:beforeSend forKey:@"beforeSend"];
|
|
145
|
-
|
|
146
|
-
// remove performance traces sample rate and traces sampler since we don't want to synchronize
|
|
147
|
-
// these configurations to the Native SDKs. The user could tho initialize the SDK manually and
|
|
148
|
-
// set themselves.
|
|
149
|
-
[mutableOptions removeObjectForKey:@"tracesSampleRate"];
|
|
150
|
-
[mutableOptions removeObjectForKey:@"tracesSampler"];
|
|
151
|
-
[mutableOptions removeObjectForKey:@"enableTracing"];
|
|
152
|
-
|
|
153
|
-
_timeToDisplay = [[RNSentryTimeToDisplay alloc] init];
|
|
154
|
-
|
|
155
|
-
#if SENTRY_TARGET_REPLAY_SUPPORTED
|
|
156
|
-
[RNSentryReplay updateOptions:mutableOptions];
|
|
157
|
-
#endif
|
|
158
|
-
|
|
159
|
-
SentryOptions *sentryOptions = [[SentryOptions alloc] initWithDict:mutableOptions
|
|
160
|
-
didFailWithError:errorPointer];
|
|
161
|
-
if (*errorPointer != nil) {
|
|
162
|
-
return nil;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Exclude Dev Server and Sentry Dsn request from Breadcrumbs
|
|
166
|
-
NSString *dsn = [self getURLFromDSN:[mutableOptions valueForKey:@"dsn"]];
|
|
167
|
-
NSString *devServerUrl = [mutableOptions valueForKey:@"devServerUrl"];
|
|
168
|
-
sentryOptions.beforeBreadcrumb
|
|
169
|
-
= ^SentryBreadcrumb *_Nullable(SentryBreadcrumb *_Nonnull breadcrumb)
|
|
170
|
-
{
|
|
171
|
-
NSString *url = breadcrumb.data[@"url"] ?: @"";
|
|
172
|
-
|
|
173
|
-
if ([@"http" isEqualToString:breadcrumb.type]
|
|
174
|
-
&& ((dsn != nil && [url hasPrefix:dsn])
|
|
175
|
-
|| (devServerUrl != nil && [url hasPrefix:devServerUrl]))) {
|
|
176
|
-
return nil;
|
|
177
|
-
}
|
|
178
|
-
return breadcrumb;
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
if ([mutableOptions valueForKey:@"enableNativeCrashHandling"] != nil) {
|
|
182
|
-
BOOL enableNativeCrashHandling = [mutableOptions[@"enableNativeCrashHandling"] boolValue];
|
|
183
|
-
|
|
184
|
-
if (!enableNativeCrashHandling) {
|
|
185
|
-
NSMutableArray *integrations = sentryOptions.integrations.mutableCopy;
|
|
186
|
-
[integrations removeObject:@"SentryCrashIntegration"];
|
|
187
|
-
sentryOptions.integrations = integrations;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Set spotlight option
|
|
192
|
-
if ([mutableOptions valueForKey:@"spotlight"] != nil) {
|
|
193
|
-
id spotlightValue = [mutableOptions valueForKey:@"spotlight"];
|
|
194
|
-
if ([spotlightValue isKindOfClass:[NSString class]]) {
|
|
195
|
-
NSLog(@"Using Spotlight on address: %@", spotlightValue);
|
|
196
|
-
sentryOptions.enableSpotlight = true;
|
|
197
|
-
sentryOptions.spotlightUrl = spotlightValue;
|
|
198
|
-
} else if ([spotlightValue isKindOfClass:[NSNumber class]]) {
|
|
199
|
-
sentryOptions.enableSpotlight = [spotlightValue boolValue];
|
|
200
|
-
id defaultSpotlightUrl = [mutableOptions valueForKey:@"defaultSidecarUrl"];
|
|
201
|
-
if (defaultSpotlightUrl != nil) {
|
|
202
|
-
sentryOptions.spotlightUrl = defaultSpotlightUrl;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Enable the App start and Frames tracking measurements
|
|
208
|
-
if ([mutableOptions valueForKey:@"enableAutoPerformanceTracing"] != nil) {
|
|
209
|
-
BOOL enableAutoPerformanceTracing =
|
|
210
|
-
[mutableOptions[@"enableAutoPerformanceTracing"] boolValue];
|
|
211
|
-
PrivateSentrySDKOnly.appStartMeasurementHybridSDKMode = enableAutoPerformanceTracing;
|
|
212
|
-
#if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST
|
|
213
|
-
PrivateSentrySDKOnly.framesTrackingMeasurementHybridSDKMode = enableAutoPerformanceTracing;
|
|
214
|
-
#endif
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Failed requests can only be enabled in one SDK to avoid duplicates
|
|
218
|
-
sentryOptions.enableCaptureFailedRequests = NO;
|
|
219
|
-
|
|
220
|
-
return sentryOptions;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
- (NSString *_Nullable)getURLFromDSN:(NSString *)dsn
|
|
224
|
-
{
|
|
225
|
-
NSURL *url = [NSURL URLWithString:dsn];
|
|
226
|
-
if (!url) {
|
|
227
|
-
return nil;
|
|
228
|
-
}
|
|
229
|
-
return [NSString stringWithFormat:@"%@://%@", url.scheme, url.host];
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
- (void)setEventOriginTag:(SentryEvent *)event
|
|
233
|
-
{
|
|
234
|
-
if (event.sdk != nil) {
|
|
235
|
-
NSString *sdkName = event.sdk[@"name"];
|
|
236
|
-
|
|
237
|
-
// If the event is from react native, it gets set
|
|
238
|
-
// there and we do not handle it here.
|
|
239
|
-
if ([sdkName isEqual:nativeSdkName]) {
|
|
240
|
-
[self setEventEnvironmentTag:event origin:@"ios" environment:@"native"];
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
- (void)setEventEnvironmentTag:(SentryEvent *)event
|
|
246
|
-
origin:(NSString *)origin
|
|
247
|
-
environment:(NSString *)environment
|
|
248
|
-
{
|
|
249
|
-
NSMutableDictionary *newTags = [NSMutableDictionary new];
|
|
250
|
-
|
|
251
|
-
if (nil != event.tags && [event.tags count] > 0) {
|
|
252
|
-
[newTags addEntriesFromDictionary:event.tags];
|
|
253
|
-
}
|
|
254
|
-
if (nil != origin) {
|
|
255
|
-
[newTags setValue:origin forKey:@"event.origin"];
|
|
256
|
-
}
|
|
257
|
-
if (nil != environment) {
|
|
258
|
-
[newTags setValue:environment forKey:@"event.environment"];
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
event.tags = newTags;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
105
|
RCT_EXPORT_METHOD(initNativeReactNavigationNewFrameTracking
|
|
265
106
|
: (RCTPromiseResolveBlock)resolve rejecter
|
|
266
107
|
: (RCTPromiseRejectBlock)reject)
|
package/ios/RNSentryReplay.mm
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#import "RNSentryReplay.h"
|
|
2
2
|
#import "RNSentryReplayBreadcrumbConverterHelper.h"
|
|
3
|
+
#import "RNSentryVersion.h"
|
|
3
4
|
#import "React/RCTTextView.h"
|
|
4
5
|
#import "Replay/RNSentryReplayMask.h"
|
|
5
6
|
#import "Replay/RNSentryReplayUnmask.h"
|
|
@@ -27,6 +28,8 @@
|
|
|
27
28
|
@"maskAllImages" : replayOptions[@"maskAllImages"] ?: [NSNull null],
|
|
28
29
|
@"maskAllText" : replayOptions[@"maskAllText"] ?: [NSNull null],
|
|
29
30
|
@"maskedViewClasses" : [RNSentryReplay getReplayRNRedactClasses:replayOptions],
|
|
31
|
+
@"sdkInfo" :
|
|
32
|
+
@ { @"name" : REACT_NATIVE_SDK_NAME, @"version" : REACT_NATIVE_SDK_PACKAGE_VERSION }
|
|
30
33
|
}
|
|
31
34
|
forKey:@"sessionReplay"];
|
|
32
35
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#import <Sentry/Sentry.h>
|
|
2
|
+
|
|
3
|
+
@interface RNSentrySDK : NSObject
|
|
4
|
+
SENTRY_NO_INIT
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @experimental
|
|
8
|
+
* Inits and configures Sentry for React Native applications using `sentry.options.json`
|
|
9
|
+
* configuration file.
|
|
10
|
+
*
|
|
11
|
+
* @discussion Call this method on the main thread. When calling it from a background thread, the
|
|
12
|
+
* SDK starts on the main thread async.
|
|
13
|
+
*/
|
|
14
|
+
+ (void)start;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @experimental
|
|
18
|
+
* Inits and configures Sentry for React Native applicationsusing `sentry.options.json`
|
|
19
|
+
* configuration file and `configureOptions` callback.
|
|
20
|
+
*
|
|
21
|
+
* The `configureOptions` callback can overwrite the config file options
|
|
22
|
+
* and add non-serializable items to the options object.
|
|
23
|
+
*
|
|
24
|
+
* @discussion Call this method on the main thread. When calling it from a background thread, the
|
|
25
|
+
* SDK starts on the main thread async.
|
|
26
|
+
*/
|
|
27
|
+
+ (void)startWithConfigureOptions:
|
|
28
|
+
(void (^_Nullable)(SentryOptions *_Nonnull options))configureOptions
|
|
29
|
+
NS_SWIFT_NAME(start(configureOptions:));
|
|
30
|
+
|
|
31
|
+
@end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#import "RNSentrySDK.h"
|
|
2
|
+
#import "RNSentryStart.h"
|
|
3
|
+
|
|
4
|
+
static NSString *SENTRY_OPTIONS_RESOURCE_NAME = @"sentry.options";
|
|
5
|
+
static NSString *SENTRY_OPTIONS_RESOURCE_TYPE = @"json";
|
|
6
|
+
|
|
7
|
+
@implementation RNSentrySDK
|
|
8
|
+
|
|
9
|
+
+ (void)start
|
|
10
|
+
{
|
|
11
|
+
[self startWithConfigureOptions:nil];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
+ (void)startWithConfigureOptions:(void (^)(SentryOptions *options))configureOptions
|
|
15
|
+
{
|
|
16
|
+
NSString *path = [[NSBundle mainBundle] pathForResource:SENTRY_OPTIONS_RESOURCE_NAME
|
|
17
|
+
ofType:SENTRY_OPTIONS_RESOURCE_TYPE];
|
|
18
|
+
|
|
19
|
+
[self start:path configureOptions:configureOptions];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
+ (void)start:(NSString *)path configureOptions:(void (^)(SentryOptions *options))configureOptions
|
|
23
|
+
{
|
|
24
|
+
NSError *readError = nil;
|
|
25
|
+
NSError *parseError = nil;
|
|
26
|
+
NSError *optionsError = nil;
|
|
27
|
+
|
|
28
|
+
NSData *_Nullable content = nil;
|
|
29
|
+
if (path != nil) {
|
|
30
|
+
content = [NSData dataWithContentsOfFile:path options:0 error:&readError];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
NSDictionary *dict = nil;
|
|
34
|
+
if (content != nil) {
|
|
35
|
+
dict = [NSJSONSerialization JSONObjectWithData:content options:0 error:&parseError];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (readError != nil) {
|
|
39
|
+
NSLog(@"[RNSentry] Failed to load options from %@, with error: %@", path,
|
|
40
|
+
readError.localizedDescription);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (parseError != nil) {
|
|
44
|
+
NSLog(@"[RNSentry] Failed to parse JSON from %@, with error: %@", path,
|
|
45
|
+
parseError.localizedDescription);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
SentryOptions *options = nil;
|
|
49
|
+
if (dict != nil) {
|
|
50
|
+
options = [RNSentryStart createOptionsWithDictionary:dict error:&optionsError];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (optionsError != nil) {
|
|
54
|
+
NSLog(@"[RNSentry] Failed to parse options from %@, with error: %@", path,
|
|
55
|
+
optionsError.localizedDescription);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (options == nil) {
|
|
59
|
+
// Fallback in case that options file could not be parsed.
|
|
60
|
+
options = [[SentryOptions alloc] init];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
[RNSentryStart updateWithReactDefaults:options];
|
|
64
|
+
if (configureOptions != nil) {
|
|
65
|
+
configureOptions(options);
|
|
66
|
+
}
|
|
67
|
+
[RNSentryStart updateWithReactFinals:options];
|
|
68
|
+
[RNSentryStart startWithOptions:options];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#import <Sentry/SentryDefines.h>
|
|
2
|
+
#import <Sentry/SentryOptions.h>
|
|
3
|
+
|
|
4
|
+
@interface RNSentryStart : NSObject
|
|
5
|
+
SENTRY_NO_INIT
|
|
6
|
+
|
|
7
|
+
+ (void)startWithOptions:(NSDictionary *_Nonnull)javascriptOptions
|
|
8
|
+
error:(NSError *_Nullable *_Nullable)errorPointer;
|
|
9
|
+
|
|
10
|
+
+ (SentryOptions *_Nullable)createOptionsWithDictionary:(NSDictionary *_Nonnull)options
|
|
11
|
+
error:(NSError *_Nonnull *_Nonnull)errorPointer;
|
|
12
|
+
|
|
13
|
+
+ (void)updateWithReactDefaults:(SentryOptions *)options;
|
|
14
|
+
+ (void)updateWithReactFinals:(SentryOptions *)options;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @experimental
|
|
18
|
+
* Inits and configures Sentry for React Native applications. Make sure to
|
|
19
|
+
* set a valid DSN.
|
|
20
|
+
*
|
|
21
|
+
* @discussion Call this method on the main thread. When calling it from a background thread, the
|
|
22
|
+
* SDK starts on the main thread async.
|
|
23
|
+
*/
|
|
24
|
+
+ (void)startWithOptions:(SentryOptions *)options NS_SWIFT_NAME(start(options:));
|
|
25
|
+
|
|
26
|
+
@end
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
#import "RNSentryStart.h"
|
|
2
|
+
#import "RNSentryReplay.h"
|
|
3
|
+
#import "RNSentryVersion.h"
|
|
4
|
+
|
|
5
|
+
#import <Sentry/PrivateSentrySDKOnly.h>
|
|
6
|
+
#import <Sentry/Sentry.h>
|
|
7
|
+
#import <Sentry/SentryOptions+HybridSDKs.h>
|
|
8
|
+
|
|
9
|
+
@implementation RNSentryStart
|
|
10
|
+
|
|
11
|
+
+ (void)startWithOptions:(NSDictionary *_Nonnull)javascriptOptions
|
|
12
|
+
error:(NSError *_Nullable *_Nullable)errorPointer
|
|
13
|
+
{
|
|
14
|
+
SentryOptions *options = [self createOptionsWithDictionary:javascriptOptions
|
|
15
|
+
error:errorPointer];
|
|
16
|
+
[self updateWithReactDefaults:options];
|
|
17
|
+
[self updateWithReactFinals:options];
|
|
18
|
+
[self startWithOptions:options];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
+ (void)startWithOptions:(SentryOptions *)options NS_SWIFT_NAME(start(options:))
|
|
22
|
+
{
|
|
23
|
+
NSString *sdkVersion = [PrivateSentrySDKOnly getSdkVersionString];
|
|
24
|
+
[PrivateSentrySDKOnly setSdkName:NATIVE_SDK_NAME andVersionString:sdkVersion];
|
|
25
|
+
[PrivateSentrySDKOnly addSdkPackage:REACT_NATIVE_SDK_PACKAGE_NAME
|
|
26
|
+
version:REACT_NATIVE_SDK_PACKAGE_VERSION];
|
|
27
|
+
|
|
28
|
+
[SentrySDK startWithOptions:options];
|
|
29
|
+
|
|
30
|
+
#if SENTRY_TARGET_REPLAY_SUPPORTED
|
|
31
|
+
[RNSentryReplay postInit];
|
|
32
|
+
#endif
|
|
33
|
+
|
|
34
|
+
[self postDidBecomeActiveNotification];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
+ (SentryOptions *_Nullable)createOptionsWithDictionary:(NSDictionary *_Nonnull)options
|
|
38
|
+
error:(NSError *_Nonnull *_Nonnull)errorPointer
|
|
39
|
+
{
|
|
40
|
+
NSMutableDictionary *mutableOptions = [options mutableCopy];
|
|
41
|
+
|
|
42
|
+
#if SENTRY_TARGET_REPLAY_SUPPORTED
|
|
43
|
+
[RNSentryReplay updateOptions:mutableOptions];
|
|
44
|
+
#endif
|
|
45
|
+
|
|
46
|
+
SentryOptions *sentryOptions = [[SentryOptions alloc] initWithDict:mutableOptions
|
|
47
|
+
didFailWithError:errorPointer];
|
|
48
|
+
if (*errorPointer != nil) {
|
|
49
|
+
return nil;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Exclude Dev Server and Sentry Dsn request from Breadcrumbs
|
|
53
|
+
NSString *dsn = [self getURLFromDSN:[mutableOptions valueForKey:@"dsn"]];
|
|
54
|
+
// TODO: For Auto Init from JS dev server is resolved automatically, for init from options file
|
|
55
|
+
// dev server has to be specified manually
|
|
56
|
+
NSString *devServerUrl = [mutableOptions valueForKey:@"devServerUrl"];
|
|
57
|
+
sentryOptions.beforeBreadcrumb
|
|
58
|
+
= ^SentryBreadcrumb *_Nullable(SentryBreadcrumb *_Nonnull breadcrumb)
|
|
59
|
+
{
|
|
60
|
+
NSString *url = breadcrumb.data[@"url"] ?: @"";
|
|
61
|
+
|
|
62
|
+
if ([@"http" isEqualToString:breadcrumb.type]
|
|
63
|
+
&& ((dsn != nil && [url hasPrefix:dsn])
|
|
64
|
+
|| (devServerUrl != nil && [url hasPrefix:devServerUrl]))) {
|
|
65
|
+
return nil;
|
|
66
|
+
}
|
|
67
|
+
return breadcrumb;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// JS options.enableNativeCrashHandling equals to native options.enableCrashHandler
|
|
71
|
+
if ([mutableOptions valueForKey:@"enableNativeCrashHandling"] != nil) {
|
|
72
|
+
BOOL enableNativeCrashHandling = [mutableOptions[@"enableNativeCrashHandling"] boolValue];
|
|
73
|
+
|
|
74
|
+
if (!enableNativeCrashHandling) {
|
|
75
|
+
NSMutableArray *integrations = sentryOptions.integrations.mutableCopy;
|
|
76
|
+
[integrations removeObject:@"SentryCrashIntegration"];
|
|
77
|
+
sentryOptions.integrations = integrations;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Set spotlight option
|
|
82
|
+
if ([mutableOptions valueForKey:@"spotlight"] != nil) {
|
|
83
|
+
id spotlightValue = [mutableOptions valueForKey:@"spotlight"];
|
|
84
|
+
if ([spotlightValue isKindOfClass:[NSString class]]) {
|
|
85
|
+
NSLog(@"Using Spotlight on address: %@", spotlightValue);
|
|
86
|
+
sentryOptions.enableSpotlight = true;
|
|
87
|
+
sentryOptions.spotlightUrl = spotlightValue;
|
|
88
|
+
} else if ([spotlightValue isKindOfClass:[NSNumber class]]) {
|
|
89
|
+
sentryOptions.enableSpotlight = [spotlightValue boolValue];
|
|
90
|
+
// TODO: For Auto init from JS set automatically for init from options file have to be
|
|
91
|
+
// set manually
|
|
92
|
+
id defaultSpotlightUrl = [mutableOptions valueForKey:@"defaultSidecarUrl"];
|
|
93
|
+
if (defaultSpotlightUrl != nil) {
|
|
94
|
+
sentryOptions.spotlightUrl = defaultSpotlightUrl;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return sentryOptions;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* This function updates the options with RNSentry defaults. These default can be
|
|
104
|
+
* overwritten by users during manual native initialization.
|
|
105
|
+
*/
|
|
106
|
+
+ (void)updateWithReactDefaults:(SentryOptions *)options
|
|
107
|
+
{
|
|
108
|
+
// Failed requests are captured only in JS to avoid duplicates
|
|
109
|
+
options.enableCaptureFailedRequests = NO;
|
|
110
|
+
|
|
111
|
+
// Tracing is only enabled in JS to avoid duplicate navigation spans
|
|
112
|
+
options.tracesSampleRate = nil;
|
|
113
|
+
options.tracesSampler = nil;
|
|
114
|
+
options.enableTracing = NO;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* This function updates options with changes RNSentry users should not change
|
|
119
|
+
* and so this is applied after the configureOptions callback during manual native initialization.
|
|
120
|
+
*/
|
|
121
|
+
+ (void)updateWithReactFinals:(SentryOptions *)options
|
|
122
|
+
{
|
|
123
|
+
SentryBeforeSendEventCallback userBeforeSend = options.beforeSend;
|
|
124
|
+
options.beforeSend = ^SentryEvent *(SentryEvent *event)
|
|
125
|
+
{
|
|
126
|
+
// Unhandled JS Exception are processed by the SDK on JS layer
|
|
127
|
+
// To avoid duplicates we drop them in the native SDKs
|
|
128
|
+
if (nil != event.exceptions.firstObject.type &&
|
|
129
|
+
[event.exceptions.firstObject.type rangeOfString:@"Unhandled JS Exception"].location
|
|
130
|
+
!= NSNotFound) {
|
|
131
|
+
return nil;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
[self setEventOriginTag:event];
|
|
135
|
+
if (userBeforeSend == nil) {
|
|
136
|
+
return event;
|
|
137
|
+
} else {
|
|
138
|
+
return userBeforeSend(event);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// App Start Hybrid mode doesn't wait for didFinishLaunchNotification and the
|
|
143
|
+
// didBecomeVisibleNotification as they will be missed when auto initializing from JS
|
|
144
|
+
// App Start measurements are created right after the tracking starts
|
|
145
|
+
PrivateSentrySDKOnly.appStartMeasurementHybridSDKMode = options.enableAutoPerformanceTracing;
|
|
146
|
+
#if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST
|
|
147
|
+
// Frames Tracking Hybrid Mode ensures tracking
|
|
148
|
+
// is enabled without tracing enabled in the native SDK
|
|
149
|
+
PrivateSentrySDKOnly.framesTrackingMeasurementHybridSDKMode
|
|
150
|
+
= options.enableAutoPerformanceTracing;
|
|
151
|
+
#endif
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
+ (void)setEventOriginTag:(SentryEvent *)event
|
|
155
|
+
{
|
|
156
|
+
if (event.sdk != nil) {
|
|
157
|
+
NSString *sdkName = event.sdk[@"name"];
|
|
158
|
+
|
|
159
|
+
// If the event is from react native, it gets set
|
|
160
|
+
// there and we do not handle it here.
|
|
161
|
+
if ([sdkName isEqual:NATIVE_SDK_NAME]) {
|
|
162
|
+
[self setEventEnvironmentTag:event origin:@"ios" environment:@"native"];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
+ (void)setEventEnvironmentTag:(SentryEvent *)event
|
|
168
|
+
origin:(NSString *)origin
|
|
169
|
+
environment:(NSString *)environment
|
|
170
|
+
{
|
|
171
|
+
NSMutableDictionary *newTags = [NSMutableDictionary new];
|
|
172
|
+
|
|
173
|
+
if (nil != event.tags && [event.tags count] > 0) {
|
|
174
|
+
[newTags addEntriesFromDictionary:event.tags];
|
|
175
|
+
}
|
|
176
|
+
if (nil != origin) {
|
|
177
|
+
[newTags setValue:origin forKey:@"event.origin"];
|
|
178
|
+
}
|
|
179
|
+
if (nil != environment) {
|
|
180
|
+
[newTags setValue:environment forKey:@"event.environment"];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
event.tags = newTags;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
+ (NSString *_Nullable)getURLFromDSN:(NSString *)dsn
|
|
187
|
+
{
|
|
188
|
+
NSURL *url = [NSURL URLWithString:dsn];
|
|
189
|
+
if (!url) {
|
|
190
|
+
return nil;
|
|
191
|
+
}
|
|
192
|
+
return [NSString stringWithFormat:@"%@://%@", url.scheme, url.host];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
static bool sentHybridSdkDidBecomeActive = NO;
|
|
196
|
+
|
|
197
|
+
+ (void)postDidBecomeActiveNotification
|
|
198
|
+
{
|
|
199
|
+
#if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST
|
|
200
|
+
BOOL appIsActive =
|
|
201
|
+
[[UIApplication sharedApplication] applicationState] == UIApplicationStateActive;
|
|
202
|
+
#else
|
|
203
|
+
BOOL appIsActive = [[NSApplication sharedApplication] isActive];
|
|
204
|
+
#endif
|
|
205
|
+
|
|
206
|
+
// If the app is active/in foreground, and we have not sent the SentryHybridSdkDidBecomeActive
|
|
207
|
+
// notification, send it.
|
|
208
|
+
if (appIsActive && !sentHybridSdkDidBecomeActive
|
|
209
|
+
&& (PrivateSentrySDKOnly.options.enableAutoSessionTracking
|
|
210
|
+
|| PrivateSentrySDKOnly.options.enableWatchdogTerminationTracking)) {
|
|
211
|
+
// Updates Native App State Manager
|
|
212
|
+
// https://github.com/getsentry/sentry-cocoa/blob/888a145b144b8077e03151a886520f332e47e297/Sources/Sentry/SentryAppStateManager.m#L136
|
|
213
|
+
// Triggers Session Tracker
|
|
214
|
+
// https://github.com/getsentry/sentry-cocoa/blob/888a145b144b8077e03151a886520f332e47e297/Sources/Sentry/SentrySessionTracker.m#L144
|
|
215
|
+
[[NSNotificationCenter defaultCenter] postNotificationName:@"SentryHybridSdkDidBecomeActive"
|
|
216
|
+
object:nil];
|
|
217
|
+
|
|
218
|
+
sentHybridSdkDidBecomeActive = true;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@end
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#import "RNSentryVersion.h"
|
|
2
|
+
|
|
3
|
+
NSString *const NATIVE_SDK_NAME = @"sentry.cocoa.react-native";
|
|
4
|
+
NSString *const REACT_NATIVE_SDK_NAME = @"sentry.javascript.react-native";
|
|
5
|
+
NSString *const REACT_NATIVE_SDK_PACKAGE_NAME = @"npm:@sentry/react-native";
|
|
6
|
+
NSString *const REACT_NATIVE_SDK_PACKAGE_VERSION = @"6.7.0-alpha.0";
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@sentry/react-native",
|
|
3
3
|
"homepage": "https://github.com/getsentry/sentry-react-native",
|
|
4
4
|
"repository": "https://github.com/getsentry/sentry-react-native",
|
|
5
|
-
"version": "6.
|
|
5
|
+
"version": "6.7.0-alpha.0",
|
|
6
6
|
"description": "Official Sentry SDK for react-native",
|
|
7
7
|
"typings": "dist/js/index.d.ts",
|
|
8
8
|
"types": "dist/js/index.d.ts",
|
|
@@ -66,22 +66,22 @@
|
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"@sentry/babel-plugin-component-annotate": "2.20.1",
|
|
69
|
-
"@sentry/browser": "8.
|
|
70
|
-
"@sentry/cli": "2.
|
|
71
|
-
"@sentry/core": "8.
|
|
72
|
-
"@sentry/react": "8.
|
|
73
|
-
"@sentry/types": "8.
|
|
74
|
-
"@sentry/utils": "8.
|
|
69
|
+
"@sentry/browser": "8.54.0",
|
|
70
|
+
"@sentry/cli": "2.41.1",
|
|
71
|
+
"@sentry/core": "8.54.0",
|
|
72
|
+
"@sentry/react": "8.54.0",
|
|
73
|
+
"@sentry/types": "8.54.0",
|
|
74
|
+
"@sentry/utils": "8.54.0"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@babel/core": "^7.25.2",
|
|
78
78
|
"@expo/metro-config": "0.19.5",
|
|
79
79
|
"@mswjs/interceptors": "^0.25.15",
|
|
80
80
|
"@react-native/babel-preset": "0.76.3",
|
|
81
|
-
"@sentry-internal/eslint-config-sdk": "8.
|
|
82
|
-
"@sentry-internal/eslint-plugin-sdk": "8.
|
|
83
|
-
"@sentry-internal/typescript": "8.
|
|
84
|
-
"@sentry/wizard": "3.
|
|
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",
|
|
84
|
+
"@sentry/wizard": "3.40.0",
|
|
85
85
|
"@testing-library/react-native": "^12.7.2",
|
|
86
86
|
"@types/jest": "^29.5.3",
|
|
87
87
|
"@types/node": "^20.9.3",
|
package/scripts/sentry-xcode.sh
CHANGED
|
@@ -51,3 +51,22 @@ fi
|
|
|
51
51
|
if [ -f "$SENTRY_COLLECT_MODULES" ]; then
|
|
52
52
|
/bin/sh "$SENTRY_COLLECT_MODULES"
|
|
53
53
|
fi
|
|
54
|
+
|
|
55
|
+
SENTRY_OPTIONS_FILE_ERROR_MESSAGE_POSTFIX="Skipping options file copy. To disable this behavior, set SENTRY_COPY_OPTIONS_FILE=false in your environment variables."
|
|
56
|
+
SENTRY_OPTIONS_FILE_NAME="sentry.options.json"
|
|
57
|
+
SENTRY_OPTIONS_FILE_DESTINATION_PATH="$CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/$SENTRY_OPTIONS_FILE_NAME"
|
|
58
|
+
[ -z "$SENTRY_OPTIONS_FILE_PATH" ] && SENTRY_OPTIONS_FILE_PATH="$RN_PROJECT_ROOT/$SENTRY_OPTIONS_FILE_NAME"
|
|
59
|
+
[ -z "$SENTRY_COPY_OPTIONS_FILE" ] && SENTRY_COPY_OPTIONS_FILE=true
|
|
60
|
+
|
|
61
|
+
if [ "$SENTRY_COPY_OPTIONS_FILE" = true ]; then
|
|
62
|
+
if [[ -z "$CONFIGURATION_BUILD_DIR" ]]; then
|
|
63
|
+
echo "[Sentry] CONFIGURATION_BUILD_DIR is not set. $SENTRY_OPTIONS_FILE_ERROR_MESSAGE_POSTFIX" 1>&2
|
|
64
|
+
elif [[ -z "$UNLOCALIZED_RESOURCES_FOLDER_PATH" ]]; then
|
|
65
|
+
echo "[Sentry] UNLOCALIZED_RESOURCES_FOLDER_PATH is not set. $SENTRY_OPTIONS_FILE_ERROR_MESSAGE_POSTFIX" 1>&2
|
|
66
|
+
elif [ ! -f "$SENTRY_OPTIONS_FILE_PATH" ]; then
|
|
67
|
+
echo "[Sentry] $SENTRY_OPTIONS_FILE_PATH not found. $SENTRY_OPTIONS_FILE_ERROR_MESSAGE_POSTFIX" 1>&2
|
|
68
|
+
else
|
|
69
|
+
cp "$SENTRY_OPTIONS_FILE_PATH" "$SENTRY_OPTIONS_FILE_DESTINATION_PATH"
|
|
70
|
+
echo "[Sentry] Copied $SENTRY_OPTIONS_FILE_PATH to $SENTRY_OPTIONS_FILE_DESTINATION_PATH"
|
|
71
|
+
fi
|
|
72
|
+
fi
|