Skip to content

Commit

Permalink
Add automatic breadcrumb logging for common UI events
Browse files Browse the repository at this point in the history
  • Loading branch information
kattrali committed Jul 22, 2016
1 parent b842627 commit 14ca6c2
Show file tree
Hide file tree
Showing 7 changed files with 231 additions and 83 deletions.
16 changes: 16 additions & 0 deletions Source/Bugsnag.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,22 @@ static NSString *_Nonnull const BugsnagSeverityInfo = @"info";
*/
+ (void)leaveBreadcrumbWithMessage:(NSString *_Nonnull)message;

/**
* Leave a "breadcrumb" log message with additional information about the
* environment at the time the breadcrumb was captured.
*
* @param block configuration block
*/
+ (void)leaveBreadcrumbWithBlock:(void(^ _Nonnull)(BugsnagBreadcrumb *_Nonnull))block;

/**
* Leave a "breadcrumb" log message each time a notification with a provided
* name is received by the application
*
* @param notificationName name of the notification to capture
*/
+ (void)leaveBreadcrumbForNotificationName:(NSString *_Nonnull)notificationName;

/**
* Set the maximum number of breadcrumbs to keep and sent to Bugsnag.
* By default, we'll keep and send the 20 most recent breadcrumb log
Expand Down
17 changes: 14 additions & 3 deletions Source/Bugsnag.m
Original file line number Diff line number Diff line change
Expand Up @@ -141,16 +141,27 @@ + (BOOL) bugsnagStarted {
if (self.notifier == nil) {
NSLog(@"Ensure you have started Bugsnag with startWithApiKey: before calling any other Bugsnag functions.");

return false;
return NO;
}
return true;
return YES;
}

+ (void) leaveBreadcrumbWithMessage:(NSString *)message {
[self.notifier.configuration.breadcrumbs addBreadcrumb:message];
[self leaveBreadcrumbWithBlock:^(BugsnagBreadcrumb * _Nonnull crumbs) {
crumbs.metadata = @{ @"message": message };
}];
}

+ (void)leaveBreadcrumbWithBlock:(void(^ _Nonnull)(BugsnagBreadcrumb *_Nonnull))block {
BugsnagBreadcrumbs *crumbs = self.notifier.configuration.breadcrumbs;
[crumbs addBreadcrumbWithBlock:block];
[self.notifier serializeBreadcrumbs];
}

+ (void)leaveBreadcrumbForNotificationName:(NSString *_Nonnull)notificationName {
[self.notifier crumbleNotification:notificationName];
}

+ (void) setBreadcrumbCapacity:(NSUInteger)capacity {
self.notifier.configuration.breadcrumbs.capacity = capacity;
}
Expand Down
30 changes: 17 additions & 13 deletions Source/BugsnagBreadcrumb.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ typedef NS_ENUM(NSUInteger, BSGBreadcrumbType) {
/**
* Any breadcrumb sent via Bugsnag.leaveBreadcrumb()
*/
BSGBreadcrumbTypeCustom,
BSGBreadcrumbTypeManual,
/**
* A call to Bugsnag.notify() (internal use only)
*/
Expand Down Expand Up @@ -69,22 +69,18 @@ typedef NS_ENUM(NSUInteger, BSGBreadcrumbType) {
BSGBreadcrumbTypeUser,
};

@class BugsnagBreadcrumb;

typedef void(^BSGBreadcrumbConfiguration)(BugsnagBreadcrumb *_Nonnull);

@interface BugsnagBreadcrumb : NSObject

@property(readonly, nonatomic, nullable) NSDate *timestamp;
@property(readonly) BSGBreadcrumbType type;
@property(readonly, nonatomic, copy, nonnull) NSString *name;
@property(readonly, nonatomic, copy, nonnull) NSDictionary *metadata;
@property(readwrite) BSGBreadcrumbType type;
@property(readwrite, nonatomic, copy, nonnull) NSString *name;
@property(readwrite, nonatomic, copy, nonnull) NSDictionary *metadata;

- (instancetype _Nullable)initWithMessage:(NSString *_Nullable)message
timestamp:(NSDate *_Nullable)date
NS_DESIGNATED_INITIALIZER;

- (instancetype _Nullable)initWithName:(NSString *_Nonnull)name
timestamp:(NSDate *_Nonnull)date
type:(BSGBreadcrumbType)type
metadata:(NSDictionary *_Nullable)metadata
NS_DESIGNATED_INITIALIZER;
+ (instancetype _Nullable)breadcrumbWithBlock:(BSGBreadcrumbConfiguration _Nonnull)block;

@end

Expand All @@ -105,6 +101,14 @@ typedef NS_ENUM(NSUInteger, BSGBreadcrumbType) {
*/
- (void)addBreadcrumb:(NSString *_Nonnull)breadcrumbMessage;

/**
* Store a new breadcrumb configured via block. Must be called from the main
* thread
*
* @param block configuration block
*/
- (void)addBreadcrumbWithBlock:(void(^ _Nonnull)(BugsnagBreadcrumb *_Nonnull))block;

/**
* Clear all stored breadcrumbs. Must be called from the main thread.
*/
Expand Down
49 changes: 24 additions & 25 deletions Source/BugsnagBreadcrumb.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#import "BugsnagBreadcrumb.h"
#import "Bugsnag.h"

NSString *const BSGBreadcrumbDefaultName = @"Custom";
NSString *const BSGBreadcrumbDefaultName = @"manual";

NSString *BSGBreadcrumbTypeValue(BSGBreadcrumbType type) {
switch (type) {
Expand All @@ -38,8 +38,8 @@
return @"error";
case BSGBreadcrumbTypeState:
return @"state";
case BSGBreadcrumbTypeCustom:
return @"custom";
case BSGBreadcrumbTypeManual:
return @"manual";
case BSGBreadcrumbTypeProcess:
return @"process";
case BSGBreadcrumbTypeRequest:
Expand All @@ -57,34 +57,27 @@ @interface BugsnagBreadcrumbs()
@implementation BugsnagBreadcrumb

- (instancetype)init {
self = [self initWithMessage:nil timestamp:nil];
return self;
}

- (instancetype)initWithMessage:(NSString *)message timestamp:(NSDate *)date {
if (message.length == 0)
return nil;

if (self = [super init]) {
_metadata = @{@"message": message};
_timestamp = date;
_type = BSGBreadcrumbTypeCustom;
_timestamp = [NSDate date];
_name = BSGBreadcrumbDefaultName;
_type = BSGBreadcrumbTypeManual;
_metadata = @{};
}
return self;
}

- (instancetype)initWithName:(NSString *)name
timestamp:(NSDate *)date
type:(BSGBreadcrumbType)type
metadata:(NSDictionary *)metadata {
if (self = [super init]) {
_name = name;
_timestamp = date;
_type = type;
_metadata = metadata;
- (BOOL)isValid {
return self.name.length > 0 && self.timestamp != nil;
}

+ (instancetype)breadcrumbWithBlock:(BSGBreadcrumbConfiguration)block {
BugsnagBreadcrumb *crumb = [self new];
if (block)
block(crumb);
if ([crumb isValid]) {
return crumb;
}
return self;
return nil;
}

@end
Expand All @@ -102,11 +95,17 @@ - (instancetype)init {
}

- (void)addBreadcrumb:(NSString *)breadcrumbMessage {
[self addBreadcrumbWithBlock:^(BugsnagBreadcrumb * _Nonnull crumb) {
crumb.metadata = @{ @"message": breadcrumbMessage };
}];
}

- (void)addBreadcrumbWithBlock:(void(^ _Nonnull)(BugsnagBreadcrumb *_Nonnull))block {
NSAssert([[NSThread currentThread] isMainThread], @"Breadcrumbs must be mutated on the main thread.");
if (self.capacity == 0) {
return;
}
BugsnagBreadcrumb* crumb = [[BugsnagBreadcrumb alloc] initWithMessage:breadcrumbMessage timestamp:[NSDate date]];
BugsnagBreadcrumb* crumb = [BugsnagBreadcrumb breadcrumbWithBlock:block];
if (crumb) {
[self resizeToFitCapacity:self.capacity - 1];
[self.breadcrumbs addObject:crumb];
Expand Down
7 changes: 7 additions & 0 deletions Source/BugsnagNotifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,11 @@
* Write breadcrumbs to the cached metadata for error reports
*/
- (void)serializeBreadcrumbs;

/**
* Listen for notifications and attach breadcrumbs when received
*
* @param notificationName name of the notification
*/
- (void)crumbleNotification:(NSString *_Nonnull)notificationName;
@end
Loading

0 comments on commit 14ca6c2

Please sign in to comment.