Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Track whether an error is handled/unhandled #164

Merged
merged 33 commits into from
Oct 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
9d484cd
add tests for handled/unhandled json serialisation
fractalwrench Sep 8, 2017
556f663
pass json serialisation tests for handled/unhandled
fractalwrench Sep 8, 2017
2a397b8
update pods
fractalwrench Sep 8, 2017
55f8e1f
update crash report to record explicit handled/un handled
fractalwrench Sep 8, 2017
a9bb0ce
handle non-fatal report json serialisation
fractalwrench Sep 8, 2017
9888554
pass tests
fractalwrench Sep 8, 2017
8d31ac7
remove obsolete todos
fractalwrench Sep 8, 2017
c20ba0b
Merge branch 'update-crash-reporter' into track-handled-unhandled
fractalwrench Sep 11, 2017
923c8ce
change constructor signature back to original
fractalwrench Sep 11, 2017
82c9882
use severity error for unhandled events
fractalwrench Sep 11, 2017
758061e
pass tests
fractalwrench Sep 11, 2017
9ea0cf8
eventHandledState -> handledState
fractalwrench Sep 15, 2017
eb22ff7
add handled state test
fractalwrench Sep 21, 2017
7dbee65
add serialisation tests for handled/unhandled json
fractalwrench Sep 21, 2017
c36a496
pass tests for non-attribute serialization
fractalwrench Sep 21, 2017
36f1b8c
pass serialization tests
fractalwrench Sep 21, 2017
b13ef07
handle user specified severity
fractalwrench Sep 21, 2017
1a9f4c7
begin adding json dict for handled state
fractalwrench Sep 21, 2017
147b0e6
serialise handled state on disk
fractalwrench Sep 21, 2017
0212f10
fix serialisation of handled state
fractalwrench Sep 21, 2017
1330610
update tvos + osx projects
fractalwrench Sep 21, 2017
f5aeb1d
device build
fractalwrench Sep 21, 2017
ec4db43
update crash report to handle signal severity reason
fractalwrench Sep 21, 2017
515e829
update to include react native promise rejection reason
fractalwrench Sep 25, 2017
c7c2dd3
update notifier to add internal notify method for react native/unity …
fractalwrench Sep 25, 2017
f62ca6e
update branch to use unity-specific kscrash enhancements
fractalwrench Sep 28, 2017
cf1812f
add boolean flag to enable thread tracing
fractalwrench Sep 28, 2017
1ff0589
Check both key and value are non-nil
kattrali Sep 29, 2017
fca6e1a
Default to unhandled exception if unparseable
kattrali Sep 29, 2017
2e4e5c6
Pass handled state through from other callers
kattrali Sep 29, 2017
1d6f116
Simplify signal attributes logic
kattrali Sep 29, 2017
da26480
Add examples of all severity reasons
kattrali Sep 29, 2017
26510de
update crash config, prevent context clearing
fractalwrench Oct 2, 2017
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
680 changes: 346 additions & 334 deletions OSX/Bugsnag.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions Source/Bugsnag.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@ static NSString *_Nonnull const BugsnagSeverityInfo = @"info";
atSeverity:(NSString *_Nullable)severity
__deprecated_msg("Use notify:block: instead and add the metadata and severity to the report directly.");

/**
* Intended for use by other clients (React Native/Unity). Calling this method directly from
* iOS is not supported.
*/
+ (void)internalClientNotify:(NSException *_Nonnull)exception
withData:(NSDictionary *_Nullable)metaData
block:(BugsnagNotifyBlock _Nullable)block;

/** Add custom data to send to Bugsnag with every exception. If value is nil,
* delete the current value for attributeName
*
Expand Down Expand Up @@ -193,4 +201,10 @@ static NSString *_Nonnull const BugsnagSeverityInfo = @"info";

+ (NSDateFormatter *_Nonnull)payloadDateFormatter;

+ (void)setSuspendThreadsForUserReported:(BOOL)suspendThreadsForUserReported;
+ (void)setReportWhenDebuggerIsAttached:(BOOL)reportWhenDebuggerIsAttached;
+ (void)setThreadTracingEnabled:(BOOL)threadTracingEnabled;
+ (void)setWriteBinaryImagesForUserReported:(BOOL)writeBinaryImagesForUserReported;


@end
26 changes: 26 additions & 0 deletions Source/Bugsnag.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#import "BugsnagNotifier.h"
#import "BugsnagSink.h"
#import "BugsnagLogger.h"
#import "BSG_KSCrash.h"

static BugsnagNotifier* bsg_g_bugsnag_notifier = NULL;

Expand Down Expand Up @@ -116,6 +117,7 @@ + (void)notify:(NSException *)exception
withData:(NSDictionary*)metaData
atSeverity:(NSString*)severity {
[[self notifier] notifyException:exception
atSeverity:BSGParseSeverity(severity)
block:^(BugsnagCrashReport * _Nonnull report) {
report.depth = 1;
report.metaData = [metaData BSG_mergedInto:
Expand All @@ -124,6 +126,14 @@ + (void)notify:(NSException *)exception
}];
}

+ (void)internalClientNotify:(NSException *_Nonnull)exception
withData:(NSDictionary *_Nullable)metaData
block:(BugsnagNotifyBlock _Nullable)block {
[self.notifier internalClientNotify:exception
withData:metaData
block:block];
}

+ (void) addAttribute:(NSString*)attributeName withValue:(id)value toTabWithName:(NSString*)tabName {
if([self bugsnagStarted]) {
[self.notifier.configuration.metaData addAttribute:attributeName withValue:value toTabWithName:tabName];
Expand Down Expand Up @@ -177,6 +187,22 @@ + (NSDateFormatter *)payloadDateFormatter {
return formatter;
}

+ (void)setSuspendThreadsForUserReported:(BOOL)suspendThreadsForUserReported {
[[BSG_KSCrash sharedInstance] setSuspendThreadsForUserReported:suspendThreadsForUserReported];
}

+ (void)setReportWhenDebuggerIsAttached:(BOOL)reportWhenDebuggerIsAttached {
[[BSG_KSCrash sharedInstance] setReportWhenDebuggerIsAttached:reportWhenDebuggerIsAttached];
}

+ (void)setThreadTracingEnabled:(BOOL)threadTracingEnabled {
[[BSG_KSCrash sharedInstance] setThreadTracingEnabled:threadTracingEnabled];
}

+ (void)setWriteBinaryImagesForUserReported:(BOOL)writeBinaryImagesForUserReported {
[[BSG_KSCrash sharedInstance] setWriteBinaryImagesForUserReported:writeBinaryImagesForUserReported];
}

@end

//
Expand Down
14 changes: 11 additions & 3 deletions Source/BugsnagCrashReport.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#import <Foundation/Foundation.h>

@class BugsnagConfiguration;
@class BugsnagHandledState;

typedef NS_ENUM(NSUInteger, BSGSeverity) {
BSGSeverityError,
Expand Down Expand Up @@ -46,21 +47,23 @@ NSString *_Nonnull BSGFormatSeverity(BSGSeverity severity);
- (instancetype _Nonnull)initWithKSReport:(NSDictionary *_Nonnull)report;

/**
* Create a basic crash report from raw parts
* Create a basic crash report from raw parts.
*
* Assumes that the exception is handled.
*
* @param name The name of the exception
* @param message The reason or message from the exception
* @param config Bugsnag configuration
* @param metaData additional data to attach to the report
* @param severity severity of the error
* @param handledState the handled state of the error
*
* @return a Bugsnag crash report
*/
- (instancetype _Nonnull)initWithErrorName:(NSString *_Nonnull)name
errorMessage:(NSString *_Nonnull)message
configuration:(BugsnagConfiguration *_Nonnull)config
metaData:(NSDictionary *_Nonnull)metaData
severity:(BSGSeverity)severity;
handledState:(BugsnagHandledState *_Nonnull)handledState;

/**
* Serialize a crash report as a JSON payload
Expand Down Expand Up @@ -147,6 +150,11 @@ NSString *_Nonnull BSGFormatSeverity(BSGSeverity severity);
* generates a section on bugsnag, displaying key/value pairs
*/
@property (nonatomic, readwrite, copy, nonnull) NSDictionary *metaData;
/**
* The event state (whether the error is handled/unhandled)
*/
@property (nonatomic, readonly, nonnull) BugsnagHandledState *handledState;

/**
* Property overrides
*/
Expand Down
49 changes: 42 additions & 7 deletions Source/BugsnagCrashReport.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#import "BugsnagLogger.h"
#import "BSGSerialization.h"
#import "BugsnagSystemInfo.h"
#import "BugsnagHandledState.h"

NSMutableDictionary *BSGFormatFrame(NSDictionary *frame,
NSArray *binaryImages) {
Expand Down Expand Up @@ -279,6 +280,7 @@ @interface BugsnagCrashReport ()
* User-provided exception metadata
*/
@property (nonatomic, readwrite, copy, nullable) NSDictionary *customException;

@end

@implementation BugsnagCrashReport
Expand All @@ -288,7 +290,6 @@ - (instancetype)initWithKSReport:(NSDictionary *)report {
_notifyReleaseStages = [report valueForKeyPath:@"user.config.notifyReleaseStages"];
_releaseStage = BSGParseReleaseStage(report);

// TODO BSG_KSCrash replacement
_error = [report valueForKeyPath:@"crash.error"];
_errorType = _error[@"type"];
_errorClass = BSGParseErrorClass(_error, _errorType);
Expand All @@ -309,25 +310,40 @@ - (instancetype)initWithKSReport:(NSDictionary *)report {
_groupingHash = BSGParseGroupingHash(report, _metaData);
_overrides = [report valueForKeyPath:@"user.overrides"];
_customException = BSGParseCustomException(report, [_errorClass copy], [_errorMessage copy]);

NSDictionary *recordedState = [report valueForKeyPath:@"user.handledState"];

if (recordedState) {
_handledState = [[BugsnagHandledState alloc] initWithDictionary:recordedState];
} else { // the event was unhandled.
BOOL isSignal = [@"signal" isEqualToString:_errorType];
SeverityReasonType severityReason = isSignal ? Signal : UnhandledException;
_handledState = [BugsnagHandledState handledStateWithSeverityReason:severityReason
severity:BSGSeverityError
attrValue:_errorClass];
}
_severity = _handledState.currentSeverity;
}
return self;
}

- (instancetype)initWithErrorName:(NSString *)name
errorMessage:(NSString *)message
configuration:(BugsnagConfiguration *)config
metaData:(NSDictionary *)metaData
severity:(BSGSeverity)severity {
- (instancetype _Nonnull)initWithErrorName:(NSString *_Nonnull)name
errorMessage:(NSString *_Nonnull)message
configuration:(BugsnagConfiguration *_Nonnull)config
metaData:(NSDictionary *_Nonnull)metaData
handledState:(BugsnagHandledState *_Nonnull)handledState {
if (self = [super init]) {
_errorClass = name;
_errorMessage = message;
_metaData = metaData ?: [NSDictionary new];
_severity = severity;
_releaseStage = config.releaseStage;
_notifyReleaseStages = config.notifyReleaseStages;
_context = BSGParseContext(nil, metaData);
_breadcrumbs = [config.breadcrumbs arrayValue];
_overrides = [NSDictionary new];

_handledState = handledState;
_severity = handledState.currentSeverity;
}
return self;
}
Expand Down Expand Up @@ -398,6 +414,11 @@ - (void)attachCustomStacktrace:(NSArray *)frames withType:(NSString *)type {
[self setOverrideProperty:@"customStacktraceType" value:type];
}

- (void)setSeverity:(BSGSeverity)severity {
_severity = severity;
_handledState.currentSeverity = severity;
}

- (void)setOverrideProperty:(NSString *)key value:(id)value {
NSMutableDictionary *metadata = [self.overrides mutableCopy];
if (value) {
Expand Down Expand Up @@ -452,6 +473,20 @@ - (NSDictionary *)serializableValueWithTopLevelData:
BSGDictSetSafeObject(event, [self app], @"app");
BSGDictSetSafeObject(event, [self context], @"context");
BSGDictInsertIfNotNil(event, self.groupingHash, @"groupingHash");

BSGDictSetSafeObject(event, @(self.handledState.unhandled), @"unhandled");

// serialize handled/unhandled into payload
NSMutableDictionary *severityReason = [NSMutableDictionary new];
NSString *reasonType = [BugsnagHandledState stringFromSeverityReason:self.handledState.calculateSeverityReasonType];
severityReason[@"type"] = reasonType;

if (self.handledState.attrKey && self.handledState.attrValue) {
severityReason[@"attributes"] = @{self.handledState.attrKey: self.handledState.attrValue};
}

BSGDictSetSafeObject(event, severityReason, @"severityReason");


// Inserted into `context` property
[metaData removeObjectForKey:@"context"];
Expand Down
45 changes: 45 additions & 0 deletions Source/BugsnagHandledState.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// BugsnagHandledState.h
// Bugsnag
//
// Created by Jamie Lynch on 21/09/2017.
// Copyright © 2017 Bugsnag. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "BugsnagCrashReport.h"

typedef NS_ENUM(NSUInteger, SeverityReasonType) {
UnhandledException,
Signal,
HandledError,
HandledException,
UserSpecifiedSeverity,
UserCallbackSetSeverity,
PromiseRejection
};

@interface BugsnagHandledState : NSObject

@property (nonatomic, readonly) BOOL unhandled;
@property (nonatomic, readonly) SeverityReasonType severityReasonType;
@property (nonatomic, readonly) BSGSeverity originalSeverity;
@property (nonatomic) BSGSeverity currentSeverity;
@property (nonatomic, readonly) SeverityReasonType calculateSeverityReasonType;
@property (nonatomic, readonly) NSString *attrValue;
@property (nonatomic, readonly) NSString *attrKey;

+ (NSString *)stringFromSeverityReason:(SeverityReasonType)severityReason;
+ (SeverityReasonType)severityReasonFromString:(NSString *)string;

+ (instancetype)handledStateWithSeverityReason:(SeverityReasonType)severityReason;

+ (instancetype)handledStateWithSeverityReason:(SeverityReasonType)severityReason
severity:(BSGSeverity)severity
attrValue:(NSString *)attrValue;

- (NSDictionary *)toJson;

- (instancetype)initWithDictionary:(NSDictionary *)dict;

@end
Loading