Skip to content
This repository was archived by the owner on Sep 14, 2020. It is now read-only.

Commit 89bb4b6

Browse files
authored
Fix session tracking auto-capture, improve stability
2 parents 6d2a7e5 + cf06208 commit 89bb4b6

14 files changed

Lines changed: 236 additions & 62 deletions

File tree

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ android {
1313
}
1414

1515
dependencies {
16-
compile 'com.bugsnag:bugsnag-android:4.2.1'
16+
compile 'com.bugsnag:bugsnag-android:4.3.1'
1717
compile 'com.facebook.react:react-native:0.20.1'
1818
}

android/src/main/java/com/bugsnag/BugsnagReactNative.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ public String getName() {
6464
return "BugsnagReactNative";
6565
}
6666

67+
@ReactMethod
68+
public void startSession() {
69+
Bugsnag.startSession();
70+
}
71+
6772
@ReactMethod
6873
public void startWithOptions(ReadableMap options) {
6974
String apiKey = null;
@@ -232,11 +237,6 @@ private void configureRuntimeOptions(Client client, ReadableMap options) {
232237
}
233238
}
234239

235-
if (options.hasKey("autoCaptureSessions")) {
236-
boolean autoCapture = options.getBoolean("autoCaptureSessions");
237-
config.setAutoCaptureSessions(autoCapture);
238-
}
239-
240240
if (options.hasKey("codeBundleId")) {
241241
String codeBundleId = options.getString("codeBundleId");
242242
if (codeBundleId != null && codeBundleId.length() > 0)
@@ -257,6 +257,13 @@ private void configureRuntimeOptions(Client client, ReadableMap options) {
257257
boolean autoCapture = options.getBoolean("automaticallyCollectBreadcrumbs");
258258
config.setAutomaticallyCollectBreadcrumbs(autoCapture);
259259
}
260+
// Process session tracking last in case the effects of other options
261+
// should be captured as a part of the session
262+
if (options.hasKey("autoCaptureSessions")) {
263+
boolean autoCapture = options.getBoolean("autoCaptureSessions");
264+
config.setAutoCaptureSessions(autoCapture);
265+
client.startFirstSession();
266+
}
260267
}
261268
}
262269

cocoa/BugsnagReactNative.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,6 @@
2727
- (void)notify:(NSDictionary *)payload;
2828
- (void)setUser:(NSDictionary *)userInfo;
2929
- (void)clearUser;
30+
- (void)startSession;
3031

3132
@end

cocoa/BugsnagReactNative.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ + (void)startWithConfiguration:(BugsnagConfiguration *)config {
187187
[[Bugsnag configuration] setUser:identifier withName:name andEmail:email];
188188
}
189189

190+
RCT_EXPORT_METHOD(startSession) {
191+
[Bugsnag startSession];
192+
}
193+
190194
RCT_EXPORT_METHOD(clearUser) {
191195
[[Bugsnag configuration] setUser:nil withName:nil andEmail:nil];
192196
}

cocoa/vendor/bugsnag-cocoa/Source/BugsnagCrashReport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,6 @@ __deprecated_msg("Use toJson: instead.");
197197
/**
198198
* Returns the enhanced error message for the thread, or nil if none exists.
199199
*/
200-
- (NSString *_Nullable)enhancedErrorMessageForThread:(NSDictionary *_Nullable)thread;
200+
- (NSString *_Nullable)enhancedErrorMessageForThread:(NSDictionary *_Nullable)thread __deprecated;
201201

202202
@end

cocoa/vendor/bugsnag-cocoa/Source/BugsnagCrashReport.m

Lines changed: 70 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,13 @@ @interface NSDictionary (BSGKSMerge)
177177
- (NSDictionary *)BSG_mergedInto:(NSDictionary *)dest;
178178
@end
179179

180+
@interface RegisterErrorData : NSObject
181+
@property (nonatomic, strong) NSString *errorClass;
182+
@property (nonatomic, strong) NSString *errorMessage;
183+
+ (instancetype)errorDataFromThreads:(NSArray *)threads;
184+
- (instancetype)initWithClass:(NSString *_Nonnull)errorClass message:(NSString *_Nonnull)errorMessage NS_DESIGNATED_INITIALIZER;
185+
@end
186+
180187
@interface BugsnagCrashReport ()
181188

182189
/**
@@ -217,10 +224,16 @@ - (instancetype)initWithKSReport:(NSDictionary *)report {
217224

218225
_error = [report valueForKeyPath:@"crash.error"];
219226
_errorType = _error[BSGKeyType];
220-
_errorClass = BSGParseErrorClass(_error, _errorType);
221-
_errorMessage = BSGParseErrorMessage(report, _error, _errorType);
222-
_binaryImages = report[@"binary_images"];
223227
_threads = [report valueForKeyPath:@"crash.threads"];
228+
RegisterErrorData *data = [RegisterErrorData errorDataFromThreads:_threads];
229+
if (data) {
230+
_errorClass = data.errorClass;
231+
_errorMessage = data.errorMessage;
232+
} else {
233+
_errorClass = BSGParseErrorClass(_error, _errorType);
234+
_errorMessage = BSGParseErrorMessage(report, _error, _errorType);
235+
}
236+
_binaryImages = report[@"binary_images"];
224237
_breadcrumbs = BSGParseBreadcrumbs(report);
225238
_severity = BSGParseSeverity(
226239
[report valueForKeyPath:@"user.state.crash.severity"]);
@@ -542,12 +555,6 @@ - (NSArray *)serializeThreadsWithException:(NSMutableDictionary *)exception {
542555
BOOL isCrashedThread = [thread[@"crashed"] boolValue];
543556

544557
if (isCrashedThread) {
545-
NSString *errMsg = [self enhancedErrorMessageForThread:thread];
546-
547-
if (errMsg) { // use enhanced error message (currently swift assertions)
548-
BSGDictInsertIfNotNil(exception, errMsg, BSGKeyMessage);
549-
}
550-
551558
NSUInteger seen = 0;
552559
NSMutableArray *stacktrace = [NSMutableArray array];
553560

@@ -593,41 +600,47 @@ - (NSArray *)serializeThreadsWithException:(NSMutableDictionary *)exception {
593600
return bugsnagThreads;
594601
}
595602

596-
/**
597-
* Returns the enhanced error message for the thread, or nil if none exists.
598-
*
599-
* This relies very heavily on heuristics rather than any documented APIs.
600-
*/
601-
- (NSString *)enhancedErrorMessageForThread:(NSDictionary *)thread {
602-
NSDictionary *notableAddresses = thread[@"notable_addresses"];
603-
NSMutableArray *msgBuffer = [NSMutableArray new];
604-
BOOL hasReservedWord = NO;
605-
606-
if (notableAddresses) {
603+
- (NSString *_Nullable)enhancedErrorMessageForThread:(NSDictionary *_Nullable)thread {
604+
return [self errorMessage];
605+
}
606+
607+
@end
608+
609+
@implementation RegisterErrorData
610+
+ (instancetype)errorDataFromThreads:(NSArray *)threads {
611+
for (NSDictionary *thread in threads) {
612+
if (![thread[@"crashed"] boolValue]) {
613+
continue;
614+
}
615+
NSDictionary *notableAddresses = thread[@"notable_addresses"];
616+
NSMutableArray *interestingValues = [NSMutableArray new];
617+
NSString *reservedWord = nil;
618+
607619
for (NSString *key in notableAddresses) {
608-
if (![key hasPrefix:@"stack"]) { // skip stack frames, only use register values
609-
NSDictionary *data = notableAddresses[key];
610-
NSString *contentValue = data[@"value"];
611-
612-
hasReservedWord = hasReservedWord || [self isReservedWord:contentValue];
613-
620+
if ([key hasPrefix:@"stack"]) { // skip stack frames, only use register values
621+
continue;
622+
}
623+
NSDictionary *data = notableAddresses[key];
624+
if (![@"string" isEqualToString:data[BSGKeyType]]) {
625+
continue;
626+
}
627+
NSString *contentValue = data[@"value"];
628+
629+
if ([self isReservedWord:contentValue]) {
630+
reservedWord = contentValue;
631+
} else if (!([[contentValue componentsSeparatedByString:@"/"] count] > 2)) {
614632
// must be a string that isn't a reserved word and isn't a filepath
615-
if ([@"string" isEqualToString:data[BSGKeyType]]
616-
&& ![self isReservedWord:contentValue]
617-
&& !([[contentValue componentsSeparatedByString:@"/"] count] > 2)) {
618-
619-
[msgBuffer addObject:contentValue];
620-
}
633+
[interestingValues addObject:contentValue];
621634
}
622635
}
623-
[msgBuffer sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
624-
}
625-
626-
if (hasReservedWord && [msgBuffer count] > 0) { // needs to have a reserved word used + a message
627-
return [msgBuffer componentsJoinedByString:@" | "];
628-
} else {
629-
return nil;
636+
637+
[interestingValues sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
638+
639+
NSString *message = [interestingValues componentsJoinedByString:@" | "];
640+
return [[RegisterErrorData alloc] initWithClass:reservedWord
641+
message:message];
630642
}
643+
return nil;
631644
}
632645

633646
/**
@@ -637,9 +650,24 @@ - (NSString *)enhancedErrorMessageForThread:(NSDictionary *)thread {
637650
*
638651
* For assert, "assertion failed" will be in one of the registers.
639652
*/
640-
- (BOOL)isReservedWord:(NSString *)contentValue {
641-
return [@"assertion failed" isEqualToString:contentValue]
642-
|| [@"fatal error" isEqualToString:contentValue];
653+
+ (BOOL)isReservedWord:(NSString *)contentValue {
654+
return [@"assertion failed" caseInsensitiveCompare:contentValue] == NSOrderedSame
655+
|| [@"fatal error" caseInsensitiveCompare:contentValue] == NSOrderedSame
656+
|| [@"precondition failed" caseInsensitiveCompare:contentValue] == NSOrderedSame;
657+
}
658+
659+
- (instancetype)init {
660+
return [self initWithClass:@"Unknown" message:@"<unset>"];
643661
}
644662

663+
- (instancetype)initWithClass:(NSString *)errorClass message:(NSString *)errorMessage {
664+
if (errorClass.length == 0) {
665+
return nil;
666+
}
667+
if (self = [super init]) {
668+
_errorClass = errorClass;
669+
_errorMessage = errorMessage;
670+
}
671+
return self;
672+
}
645673
@end

cocoa/vendor/bugsnag-cocoa/Source/BugsnagFileStore.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,5 @@
7070
+ (NSString *)findReportStorePath:(NSString *)customDirectory
7171
bundleName:(NSString *)bundleName;
7272

73-
@end
73+
- (NSString *)fileIdFromFilename:(NSString *)filename;
74+
@end

cocoa/vendor/bugsnag-cocoa/Source/BugsnagNotifier.m

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
#import <AppKit/AppKit.h>
4242
#endif
4343

44-
NSString *const NOTIFIER_VERSION = @"5.15.0";
44+
NSString *const NOTIFIER_VERSION = @"5.15.3";
4545
NSString *const NOTIFIER_URL = @"https://github.com/bugsnag/bugsnag-cocoa";
4646
NSString *const BSTabCrash = @"crash";
4747
NSString *const BSAttributeDepth = @"depth";
@@ -410,7 +410,6 @@ - (void)willEnterBackground:(id)sender {
410410

411411
- (void)sessionTick:(id)sender {
412412
[self.sessionTracker send];
413-
NSLog(@"Session Tick!");
414413
}
415414

416415
- (void)flushPendingReports {

cocoa/vendor/bugsnag-cocoa/Source/BugsnagSink.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ - (void)filterReports:(NSArray *)reports
114114
- (NSDictionary *)getBodyFromReports:(NSArray *)reports {
115115
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
116116
BSGDictSetSafeObject(data, [Bugsnag notifier].details, BSGKeyNotifier);
117+
BSGDictSetSafeObject(data, [Bugsnag notifier].configuration.apiKey, BSGKeyApiKey);
117118

118119
NSMutableArray *formatted =
119120
[[NSMutableArray alloc] initWithCapacity:[reports count]];

cocoa/vendor/bugsnag-cocoa/Source/KSCrash/Source/KSCrash/Recording/BSG_KSCrashDoctor.m

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
typedef enum {
1616
BSG_CPUFamilyUnknown,
1717
BSG_CPUFamilyArm,
18+
BSG_CPUFamilyArm64,
1819
BSG_CPUFamilyX86,
1920
BSG_CPUFamilyX86_64
2021
} BSG_CPUFamily;
@@ -170,15 +171,17 @@ - (NSDictionary *)errorReport:(NSDictionary *)report {
170171
- (BSG_CPUFamily)cpuFamily:(NSDictionary *)report {
171172
NSDictionary *system = [self systemReport:report];
172173
NSString *cpuArch = system[@BSG_KSSystemField_CPUArch];
174+
if ([cpuArch isEqualToString:@"arm64"]) {
175+
return BSG_CPUFamilyArm64;
176+
}
173177
if ([cpuArch rangeOfString:@"arm"].location == 0) {
174178
return BSG_CPUFamilyArm;
175179
}
176180
if ([cpuArch rangeOfString:@"i"].location == 0 &&
177181
[cpuArch rangeOfString:@"86"].location == 2) {
178182
return BSG_CPUFamilyX86;
179183
}
180-
if ([cpuArch rangeOfString:@"x86_64" options:NSCaseInsensitiveSearch]
181-
.location != NSNotFound) {
184+
if ([@[@"x86_64", @"x86"] containsObject:cpuArch]) {
182185
return BSG_CPUFamilyX86_64;
183186
}
184187
return BSG_CPUFamilyUnknown;
@@ -199,6 +202,18 @@ - (NSString *)registerNameForFamily:(BSG_CPUFamily)family
199202
return @"r3";
200203
}
201204
}
205+
case BSG_CPUFamilyArm64: {
206+
switch (index) {
207+
case 0:
208+
return @"x0";
209+
case 1:
210+
return @"x1";
211+
case 2:
212+
return @"x2";
213+
case 3:
214+
return @"x3";
215+
}
216+
}
202217
case BSG_CPUFamilyX86: {
203218
switch (index) {
204219
case 0:
@@ -367,10 +382,13 @@ - (BSG_KSCrashDoctorFunctionCall *)lastFunctionCall:(NSDictionary *)report {
367382
BSG_CPUFamily family = [self cpuFamily:report];
368383
NSDictionary *registers =
369384
[self basicRegistersFromThreadReport:crashedThread];
370-
NSArray *regNames = @[[self registerNameForFamily:family paramIndex:0],
371-
[self registerNameForFamily:family paramIndex:1],
372-
[self registerNameForFamily:family paramIndex:2],
373-
[self registerNameForFamily:family paramIndex:3]];
385+
NSMutableArray *regNames = [NSMutableArray arrayWithCapacity:4];
386+
for (int paramIndex = 0; paramIndex <= 3; paramIndex++) {
387+
NSString *regName = [self registerNameForFamily:family paramIndex:paramIndex];
388+
if (regName.length > 0) {
389+
[regNames addObject:regName];
390+
}
391+
}
374392
NSMutableArray *params = [NSMutableArray arrayWithCapacity:4];
375393
for (NSString *regName in regNames) {
376394
BSG_KSCrashDoctorParam *param = [[BSG_KSCrashDoctorParam alloc] init];

0 commit comments

Comments
 (0)