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

Remove in-memory breadcrumbs #861

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 4 additions & 1 deletion Bugsnag/Breadcrumbs/BugsnagBreadcrumbs.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ NS_ASSUME_NONNULL_BEGIN

- (instancetype)initWithConfiguration:(BugsnagConfiguration *)config;

/**
* The current breadcrumbs, loaded from disk.
*/
@property (readonly) NSArray<BugsnagBreadcrumb *> *breadcrumbs;

/**
Expand All @@ -47,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
- (nullable NSArray<NSDictionary *> *)cachedBreadcrumbs;

/**
* Removes breadcrumbs from disk and memory.
* Removes breadcrumbs from disk.
*/
- (void)removeAllBreadcrumbs;

Expand Down
26 changes: 13 additions & 13 deletions Bugsnag/Breadcrumbs/BugsnagBreadcrumbs.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ + (instancetype _Nullable)breadcrumbFromDict:(NSDictionary *_Nonnull)dict;
@interface BugsnagBreadcrumbs ()

@property BugsnagConfiguration *config;
@property NSArray<BugsnagBreadcrumb *> *breadcrumbs;
@property unsigned int nextFileNumber;
@property unsigned int maxBreadcrumbs;

Expand All @@ -57,7 +56,6 @@ - (instancetype)initWithConfiguration:(BugsnagConfiguration *)config {
}

_config = config;
_breadcrumbs = [NSArray array];
// Capture maxBreadcrumbs to protect against config being changed after initialization
_maxBreadcrumbs = (unsigned int)config.maxBreadcrumbs;

Expand All @@ -73,6 +71,10 @@ - (instancetype)initWithConfiguration:(BugsnagConfiguration *)config {
return self;
}

- (NSArray<BugsnagBreadcrumb *> *)breadcrumbs {
return [self loadBreadcrumbsAsDictionaries:NO] ?: @[];
}

- (void)addBreadcrumb:(NSString *)breadcrumbMessage {
[self addBreadcrumbWithBlock:^(BugsnagBreadcrumb *_Nonnull crumb) {
crumb.message = breadcrumbMessage;
Expand All @@ -93,12 +95,6 @@ - (void)addBreadcrumbWithBlock:(BSGBreadcrumbConfiguration)block {
}
unsigned int fileNumber;
@synchronized (self) {
NSMutableArray<BugsnagBreadcrumb *> *breadcrumbs = [self.breadcrumbs mutableCopy];
if (breadcrumbs.count >= self.maxBreadcrumbs) {
[breadcrumbs removeObjectAtIndex:0];
}
[breadcrumbs addObject:crumb];
self.breadcrumbs = [NSArray arrayWithArray:breadcrumbs];
fileNumber = self.nextFileNumber;
self.nextFileNumber = fileNumber + 1;
if (fileNumber + 1 > self.maxBreadcrumbs) {
Expand All @@ -124,7 +120,6 @@ - (BOOL)shouldSendBreadcrumb:(BugsnagBreadcrumb *)crumb {

- (void)removeAllBreadcrumbs {
@synchronized (self) {
self.breadcrumbs = @[];
self.nextFileNumber = 0;
g_context.firstFileNumber = 0;
g_context.nextFileNumber = 0;
Expand Down Expand Up @@ -170,6 +165,10 @@ - (void)writeBreadcrumbData:(NSData *)data toFileNumber:(unsigned int)fileNumber
}

- (nullable NSArray<NSDictionary *> *)cachedBreadcrumbs {
return [self loadBreadcrumbsAsDictionaries:YES];
}

- (nullable NSArray *)loadBreadcrumbsAsDictionaries:(BOOL)asDictionaries {
NSError *error = nil;

NSArray<NSString *> *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:_cachePath error:&error];
Expand All @@ -178,7 +177,7 @@ - (void)writeBreadcrumbData:(NSData *)data toFileNumber:(unsigned int)fileNumber
return nil;
}

NSMutableArray<NSDictionary *> *dictionaries = [NSMutableArray array];
NSMutableArray<NSDictionary *> *breadcrumbs = [NSMutableArray array];

for (NSString *file in [filenames sortedArrayUsingSelector:@selector(compare:)]) {
NSString *path = [self.cachePath stringByAppendingPathComponent:file];
Expand All @@ -192,15 +191,16 @@ - (void)writeBreadcrumbData:(NSData *)data toFileNumber:(unsigned int)fileNumber
bsg_log_err(@"Unable to parse breadcrumb: %@", error);
continue;
}
BugsnagBreadcrumb *breadcrumb;
if (![JSONObject isKindOfClass:[NSDictionary class]] ||
![BugsnagBreadcrumb breadcrumbFromDict:JSONObject]) {
!(breadcrumb = [BugsnagBreadcrumb breadcrumbFromDict:JSONObject])) {
bsg_log_err(@"Unexpected breadcrumb payload in file %@", file);
continue;
}
[dictionaries addObject:JSONObject];
[breadcrumbs addObject:asDictionaries ? JSONObject : breadcrumb];
}

return dictionaries;
return breadcrumbs;
}

- (void)deleteBreadcrumbFiles {
Expand Down
14 changes: 10 additions & 4 deletions Tests/BugsnagBreadcrumbsTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -80,22 +80,25 @@ - (void)setUp {
- (void)testDefaultCount {
BugsnagConfiguration *config = [[BugsnagConfiguration alloc] initWithApiKey:DUMMY_APIKEY_32CHAR_1];
BugsnagBreadcrumbs *crumbs = [[BugsnagBreadcrumbs alloc] initWithConfiguration:config];
[crumbs removeAllBreadcrumbs];
XCTAssertTrue(crumbs.breadcrumbs.count == 0);
}

- (void)testMaxBreadcrumbs {
BugsnagConfiguration *config = [[BugsnagConfiguration alloc] initWithApiKey:DUMMY_APIKEY_32CHAR_1];
config.maxBreadcrumbs = 3;
self.crumbs = [[BugsnagBreadcrumbs alloc] initWithConfiguration:config];
[self.crumbs removeAllBreadcrumbs];
[self.crumbs addBreadcrumb:@"Crumb 1"];
[self.crumbs addBreadcrumb:@"Crumb 2"];
[self.crumbs addBreadcrumb:@"Crumb 3"];
[self.crumbs addBreadcrumb:@"Clear notifications"];
awaitBreadcrumbSync(self.crumbs);
XCTAssertEqual(self.crumbs.breadcrumbs.count, 3);
XCTAssertEqualObjects(self.crumbs.breadcrumbs[0].message, @"Crumb 2");
XCTAssertEqualObjects(self.crumbs.breadcrumbs[1].message, @"Crumb 3");
XCTAssertEqualObjects(self.crumbs.breadcrumbs[2].message, @"Clear notifications");
NSArray<BugsnagBreadcrumb *> *breadcrumbs = self.crumbs.breadcrumbs;
XCTAssertEqual(breadcrumbs.count, 3);
XCTAssertEqualObjects(breadcrumbs[0].message, @"Crumb 2");
XCTAssertEqualObjects(breadcrumbs[1].message, @"Crumb 3");
XCTAssertEqualObjects(breadcrumbs[2].message, @"Clear notifications");
}

- (void)testBreadcrumbsInvalidKey {
Expand All @@ -118,6 +121,7 @@ - (void)testEmptyCapacity {
BugsnagConfiguration *config = [[BugsnagConfiguration alloc] initWithApiKey:DUMMY_APIKEY_32CHAR_1];
config.maxBreadcrumbs = 0;
self.crumbs = [[BugsnagBreadcrumbs alloc] initWithConfiguration:config];
[self.crumbs removeAllBreadcrumbs];
[self.crumbs addBreadcrumb:@"Clear notifications"];
XCTAssertEqual(self.crumbs.breadcrumbs.count, 0);
}
Expand Down Expand Up @@ -234,6 +238,7 @@ - (void)testDefaultDiscardByType {
- (void)testAlwaysAllowManual {
BugsnagConfiguration *config = [[BugsnagConfiguration alloc] initWithApiKey:DUMMY_APIKEY_32CHAR_1];
self.crumbs = [[BugsnagBreadcrumbs alloc] initWithConfiguration:config];
[self.crumbs removeAllBreadcrumbs];
[self.crumbs addBreadcrumb:@"this is a test"];
awaitBreadcrumbSync(self.crumbs);
NSArray *value = [self.crumbs arrayValue];
Expand All @@ -249,6 +254,7 @@ - (void)testAlwaysAllowManual {
- (void)testDiscardByTypeDoesNotApply {
BugsnagConfiguration *config = [[BugsnagConfiguration alloc] initWithApiKey:DUMMY_APIKEY_32CHAR_1];
self.crumbs = [[BugsnagBreadcrumbs alloc] initWithConfiguration:config];
[self.crumbs removeAllBreadcrumbs];
// Don't discard this
[self.crumbs addBreadcrumbWithBlock:^(BugsnagBreadcrumb *_Nonnull crumb) {
crumb.type = BSGBreadcrumbTypeState;
Expand Down