diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f5715194..2ffd0afc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ Bugsnag Notifiers on other platforms. ## Enhancements +* Remove unused APIs from `BugsnagBreadcrumb` interface + [#502](https://github.com/bugsnag/bugsnag-cocoa/pull/502) + * Remove notify method variants from public api on `Bugsnag` [#497](https://github.com/bugsnag/bugsnag-cocoa/pull/497) diff --git a/OSX/Bugsnag.xcodeproj/project.pbxproj b/OSX/Bugsnag.xcodeproj/project.pbxproj index 9f32120f7..682d1c876 100644 --- a/OSX/Bugsnag.xcodeproj/project.pbxproj +++ b/OSX/Bugsnag.xcodeproj/project.pbxproj @@ -59,6 +59,8 @@ E762E9F91F73F7F300E82B43 /* BugsnagHandledStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E762E9F71F73F7E900E82B43 /* BugsnagHandledStateTest.m */; }; E762E9FC1F73F80200E82B43 /* BugsnagHandledState.h in Headers */ = {isa = PBXBuildFile; fileRef = E762E9FA1F73F80200E82B43 /* BugsnagHandledState.h */; }; E762E9FD1F73F80200E82B43 /* BugsnagHandledState.m in Sources */ = {isa = PBXBuildFile; fileRef = E762E9FB1F73F80200E82B43 /* BugsnagHandledState.m */; }; + E77526C0242D0E180077A42F /* BugsnagBreadcrumbs.m in Sources */ = {isa = PBXBuildFile; fileRef = E77526BE242D0E180077A42F /* BugsnagBreadcrumbs.m */; }; + E77526C1242D0E180077A42F /* BugsnagBreadcrumbs.h in Headers */ = {isa = PBXBuildFile; fileRef = E77526BF242D0E180077A42F /* BugsnagBreadcrumbs.h */; }; E79148461FD82B36003EFEBF /* BugsnagSession.h in Headers */ = {isa = PBXBuildFile; fileRef = E79148331FD82B34003EFEBF /* BugsnagSession.h */; }; E79148471FD82B36003EFEBF /* BugsnagKSCrashSysInfoParser.h in Headers */ = {isa = PBXBuildFile; fileRef = E79148341FD82B34003EFEBF /* BugsnagKSCrashSysInfoParser.h */; }; E79148481FD82B36003EFEBF /* BugsnagUser.h in Headers */ = {isa = PBXBuildFile; fileRef = E79148351FD82B34003EFEBF /* BugsnagUser.h */; }; @@ -252,6 +254,8 @@ E762E9F71F73F7E900E82B43 /* BugsnagHandledStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BugsnagHandledStateTest.m; path = ../Tests/BugsnagHandledStateTest.m; sourceTree = SOURCE_ROOT; }; E762E9FA1F73F80200E82B43 /* BugsnagHandledState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BugsnagHandledState.h; path = ../Source/BugsnagHandledState.h; sourceTree = SOURCE_ROOT; }; E762E9FB1F73F80200E82B43 /* BugsnagHandledState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BugsnagHandledState.m; path = ../Source/BugsnagHandledState.m; sourceTree = SOURCE_ROOT; }; + E77526BE242D0E180077A42F /* BugsnagBreadcrumbs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BugsnagBreadcrumbs.m; path = ../Source/BugsnagBreadcrumbs.m; sourceTree = ""; }; + E77526BF242D0E180077A42F /* BugsnagBreadcrumbs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BugsnagBreadcrumbs.h; path = ../Source/BugsnagBreadcrumbs.h; sourceTree = ""; }; E791482B1FD82B0C003EFEBF /* BugsnagSessionTrackerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagSessionTrackerTest.m; sourceTree = ""; }; E791482C1FD82B0C003EFEBF /* BugsnagSessionTrackingPayloadTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagSessionTrackingPayloadTest.m; sourceTree = ""; }; E791482D1FD82B0C003EFEBF /* BugsnagSessionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagSessionTest.m; sourceTree = ""; }; @@ -434,6 +438,8 @@ 8A2C8FA31C6BC1F700846019 /* Bugsnag */ = { isa = PBXGroup; children = ( + E77526BF242D0E180077A42F /* BugsnagBreadcrumbs.h */, + E77526BE242D0E180077A42F /* BugsnagBreadcrumbs.m */, E72AE1F8241A4E7500ED8972 /* BugsnagPluginClient.h */, E72AE1F7241A4E7500ED8972 /* BugsnagPluginClient.m */, 00D7AC9B23E97F8100FBE4A7 /* BugsnagEvent.h */, @@ -787,6 +793,7 @@ E79E6BC61F4E3850002B35F9 /* BSG_KSObjC.h in Headers */, E79E6BCE1F4E3850002B35F9 /* BSG_KSString.h in Headers */, E79E6B921F4E3850002B35F9 /* BSG_KSCrashReportFields.h in Headers */, + E77526C1242D0E180077A42F /* BugsnagBreadcrumbs.h in Headers */, E79E6BD91F4E3850002B35F9 /* BSG_RFC3339DateTool.h in Headers */, E72352C11F55924A00436528 /* BSGConnectivity.h in Headers */, 8A2C8FDD1C6BC2C800846019 /* BugsnagSink.h in Headers */, @@ -908,6 +915,7 @@ E79E6B8F1F4E3850002B35F9 /* BSG_KSCrashDoctor.m in Sources */, E791484E1FD82B36003EFEBF /* BugsnagKSCrashSysInfoParser.m in Sources */, E791484F1FD82B36003EFEBF /* BugsnagSessionTrackingPayload.m in Sources */, + E77526C0242D0E180077A42F /* BugsnagBreadcrumbs.m in Sources */, E72AE1F9241A4E7500ED8972 /* BugsnagPluginClient.m in Sources */, E79E6B971F4E3850002B35F9 /* BSG_KSCrashState.m in Sources */, 8A6C6FB12257884C00E8EF24 /* BSGOutOfMemoryWatchdog.m in Sources */, diff --git a/Source/BugsnagBreadcrumb.h b/Source/BugsnagBreadcrumb.h index 5d522e323..b79448b9c 100644 --- a/Source/BugsnagBreadcrumb.h +++ b/Source/BugsnagBreadcrumb.h @@ -99,60 +99,6 @@ typedef void (^BSGBreadcrumbConfiguration)(BugsnagBreadcrumb *_Nonnull); @property(readwrite) BSGBreadcrumbType type; @property(readwrite, copy, nonnull) NSString *message; @property(readwrite, copy, nonnull) NSDictionary *metadata; - -+ (instancetype _Nullable)breadcrumbWithBlock: - (BSGBreadcrumbConfiguration _Nonnull)block; - -+ (instancetype _Nullable)breadcrumbFromDict:(NSDictionary *_Nonnull)dict; @end -@interface BugsnagBreadcrumbs : NSObject - -/** - * The maximum number of breadcrumbs. Resizable. - */ -@property(assign, readwrite) NSUInteger capacity; - -/** Number of breadcrumbs accumulated */ -@property(assign, readonly) NSUInteger count; -/** - * Path where breadcrumbs are persisted on disk - */ -@property (nonatomic, readonly, strong, nullable) NSString *cachePath; - -/** - * Store a new breadcrumb with a provided message. - */ -- (void)addBreadcrumb:(NSString *_Nonnull)breadcrumbMessage; - -/** - * Store a new breadcrumb configured via block. - * - * @param block configuration block - */ -- (void)addBreadcrumbWithBlock: - (void (^_Nonnull)(BugsnagBreadcrumb *_Nonnull))block; - -/** - * Clear all stored breadcrumbs. - */ -- (void)clearBreadcrumbs; - -/** Breadcrumb object for a particular index or nil */ -- (BugsnagBreadcrumb *_Nullable)objectAtIndexedSubscript:(NSUInteger)index; -/** - * Serializable array representation of breadcrumbs, represented as nested - * strings in the format: - * [[timestamp,message]...] - * - * returns nil if empty - */ -- (NSArray *_Nullable)arrayValue; - -/** - * The types of breadcrumbs which will be automatically captured. - * By default, this is all types. - */ -@property BSGEnabledBreadcrumbType enabledBreadcrumbTypes; -@end diff --git a/Source/BugsnagBreadcrumb.m b/Source/BugsnagBreadcrumb.m index de8fcfbaf..bac159a58 100644 --- a/Source/BugsnagBreadcrumb.m +++ b/Source/BugsnagBreadcrumb.m @@ -24,6 +24,7 @@ // THE SOFTWARE. // #import "BugsnagBreadcrumb.h" +#import "BugsnagBreadcrumbs.h" #import "Bugsnag.h" #import "BugsnagLogger.h" #import "BugsnagKeys.h" @@ -69,12 +70,6 @@ BSGBreadcrumbType BSGBreadcrumbTypeFromString(NSString *value) { } } -@interface BugsnagBreadcrumbs () - -@property(nonatomic, readwrite, strong) NSMutableArray *breadcrumbs; -@property(nonatomic, readonly, strong) dispatch_queue_t readWriteQueue; -@end - @implementation BugsnagBreadcrumb - (instancetype)init { @@ -205,154 +200,3 @@ + (instancetype)breadcrumbFromDict:(NSDictionary *)dict { @end -@implementation BugsnagBreadcrumbs - -NSUInteger BreadcrumbsDefaultCapacity = 25; - -- (instancetype)init { - static NSString *const BSGBreadcrumbCacheFileName = @"bugsnag_breadcrumbs.json"; - if (self = [super init]) { - _breadcrumbs = [NSMutableArray new]; - _capacity = BreadcrumbsDefaultCapacity; - _enabledBreadcrumbTypes = BSGEnabledBreadcrumbTypeAll; - _readWriteQueue = dispatch_queue_create("com.bugsnag.BreadcrumbRead", - DISPATCH_QUEUE_SERIAL); - NSString *cacheDir = [NSSearchPathForDirectoriesInDomains( - NSCachesDirectory, NSUserDomainMask, YES) firstObject]; - if (cacheDir != nil) { - _cachePath = [cacheDir stringByAppendingPathComponent: - BSGBreadcrumbCacheFileName]; - } - } - return self; -} - -- (void)addBreadcrumb:(NSString *)breadcrumbMessage { - [self addBreadcrumbWithBlock:^(BugsnagBreadcrumb *_Nonnull crumb) { - crumb.message = breadcrumbMessage; - }]; -} - -- (void)addBreadcrumbWithBlock: - (void (^_Nonnull)(BugsnagBreadcrumb *_Nonnull))block { - if (self.capacity == 0) { - return; - } - BugsnagBreadcrumb *crumb = [BugsnagBreadcrumb breadcrumbWithBlock:block]; - if (crumb) { - [self resizeToFitCapacity:self.capacity - 1]; - dispatch_barrier_sync(self.readWriteQueue, ^{ - [self.breadcrumbs addObject:crumb]; - // Serialize crumbs to disk inside barrier to avoid simultaneous - // access to the file - if (self.cachePath != nil) { - static NSString *const arrayKeyPath = @"objectValue"; - NSArray *items = [self.breadcrumbs valueForKeyPath:arrayKeyPath]; - if ([NSJSONSerialization isValidJSONObject:items]) { - NSError *error = nil; - NSData *data = [NSJSONSerialization dataWithJSONObject:items - options:0 - error:&error]; - [data writeToFile:self.cachePath atomically:NO]; - if (error != nil) { - bsg_log_err(@"Failed to write breadcrumbs to disk: %@", error); - } - } - } - }); - } -} - -- (NSArray *)cachedBreadcrumbs { - __block NSArray *cache = nil; - dispatch_barrier_sync(self.readWriteQueue, ^{ - NSError *error = nil; - NSData *data = [NSData dataWithContentsOfFile:self.cachePath options:0 error:&error]; - if (error == nil) { - cache = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; - } - if (error != nil) { - bsg_log_err(@"Failed to read breadcrumbs from disk: %@", error); - } - }); - return [cache isKindOfClass:[NSArray class]] ? cache : nil; -} - -@synthesize capacity = _capacity; - -- (NSUInteger)capacity { - @synchronized (self) { - return _capacity; - } -} - -- (void)setCapacity:(NSUInteger)capacity { - @synchronized (self) { - if (capacity == _capacity) { - return; - } - [self resizeToFitCapacity:capacity]; - [self willChangeValueForKey:NSStringFromSelector(@selector(capacity))]; - _capacity = MIN(100, capacity); - [self didChangeValueForKey:NSStringFromSelector(@selector(capacity))]; - } -} - -- (void)clearBreadcrumbs { - dispatch_barrier_sync(self.readWriteQueue, ^{ - [self.breadcrumbs removeAllObjects]; - }); -} - -- (NSUInteger)count { - return self.breadcrumbs.count; -} - -- (BugsnagBreadcrumb *)objectAtIndexedSubscript:(NSUInteger)index { - if (index < [self count]) { - __block BugsnagBreadcrumb *crumb = nil; - dispatch_barrier_sync(self.readWriteQueue, ^{ - crumb = self.breadcrumbs[index]; - }); - return crumb; - } - return nil; -} - -- (NSArray *)arrayValue { - if ([self count] == 0) { - return nil; - } - __block NSMutableArray *contents = - [[NSMutableArray alloc] initWithCapacity:[self count]]; - dispatch_barrier_sync(self.readWriteQueue, ^{ - for (BugsnagBreadcrumb *crumb in self.breadcrumbs) { - NSDictionary *objectValue = [crumb objectValue]; - NSError *error = nil; - @try { - if (![NSJSONSerialization isValidJSONObject:objectValue]) { - bsg_log_err(@"Unable to serialize breadcrumb: Not a valid " - @"JSON object"); - continue; - } - [contents addObject:objectValue]; - } @catch (NSException *exception) { - bsg_log_err(@"Unable to serialize breadcrumb: %@", error); - } - } - }); - return contents; -} - -- (void)resizeToFitCapacity:(NSUInteger)capacity { - if (capacity == 0) { - [self clearBreadcrumbs]; - } else if ([self count] > capacity) { - dispatch_barrier_sync(self.readWriteQueue, ^{ - [self.breadcrumbs - removeObjectsInRange:NSMakeRange(0, self.count - capacity)]; - }); - } -} - -@end diff --git a/Source/BugsnagBreadcrumbs.h b/Source/BugsnagBreadcrumbs.h new file mode 100644 index 000000000..33989f6ad --- /dev/null +++ b/Source/BugsnagBreadcrumbs.h @@ -0,0 +1,63 @@ +// +// BugsnagBreadcrumbs.h +// Bugsnag +// +// Created by Jamie Lynch on 26/03/2020. +// Copyright © 2020 Bugsnag. All rights reserved. +// + +#import + +#import "BugsnagBreadcrumb.h" + +@interface BugsnagBreadcrumbs : NSObject + +/** + * The maximum number of breadcrumbs. Resizable. + */ +@property(assign, readwrite) NSUInteger capacity; + +/** Number of breadcrumbs accumulated */ +@property(assign, readonly) NSUInteger count; +/** + * Path where breadcrumbs are persisted on disk + */ +@property (nonatomic, readonly, strong, nullable) NSString *cachePath; + +/** + * Store a new breadcrumb with a provided message. + */ +- (void)addBreadcrumb:(NSString *_Nonnull)breadcrumbMessage; + +/** + * Store a new breadcrumb configured via block. + * + * @param block configuration block + */ +- (void)addBreadcrumbWithBlock: + (void (^_Nonnull)(BugsnagBreadcrumb *_Nonnull))block; + +/** + * Clear all stored breadcrumbs. + */ +- (void)clearBreadcrumbs; + +/** Breadcrumb object for a particular index or nil */ +- (BugsnagBreadcrumb *_Nullable)objectAtIndexedSubscript:(NSUInteger)index; + +/** + * Serializable array representation of breadcrumbs, represented as nested + * strings in the format: + * [[timestamp,message]...] + * + * returns nil if empty + */ +- (NSArray *_Nullable)arrayValue; + +/** + * The types of breadcrumbs which will be automatically captured. + * By default, this is all types. + */ +@property BSGEnabledBreadcrumbType enabledBreadcrumbTypes; + +@end diff --git a/Source/BugsnagBreadcrumbs.m b/Source/BugsnagBreadcrumbs.m new file mode 100644 index 000000000..96bda7761 --- /dev/null +++ b/Source/BugsnagBreadcrumbs.m @@ -0,0 +1,177 @@ +// +// BugsnagBreadcrumbs.m +// Bugsnag +// +// Created by Jamie Lynch on 26/03/2020. +// Copyright © 2020 Bugsnag. All rights reserved. +// + + +#import "BugsnagBreadcrumbs.h" +#import "BugsnagBreadcrumb.h" +#import "BugsnagLogger.h" +#import "Private.h" + +@interface BugsnagBreadcrumb () ++ (instancetype _Nullable)breadcrumbWithBlock: + (BSGBreadcrumbConfiguration _Nonnull)block; ++ (instancetype _Nullable)breadcrumbFromDict:(NSDictionary *_Nonnull)dict; +@end + +@interface BugsnagBreadcrumbs () + +@property(nonatomic, readwrite, strong) NSMutableArray *breadcrumbs; +@property(nonatomic, readonly, strong) dispatch_queue_t readWriteQueue; +@end + +@implementation BugsnagBreadcrumbs + +NSUInteger BreadcrumbsDefaultCapacity = 25; + +- (instancetype)init { + static NSString *const BSGBreadcrumbCacheFileName = @"bugsnag_breadcrumbs.json"; + if (self = [super init]) { + _breadcrumbs = [NSMutableArray new]; + _capacity = BreadcrumbsDefaultCapacity; + _enabledBreadcrumbTypes = BSGEnabledBreadcrumbTypeAll; + _readWriteQueue = dispatch_queue_create("com.bugsnag.BreadcrumbRead", + DISPATCH_QUEUE_SERIAL); + NSString *cacheDir = [NSSearchPathForDirectoriesInDomains( + NSCachesDirectory, NSUserDomainMask, YES) firstObject]; + if (cacheDir != nil) { + _cachePath = [cacheDir stringByAppendingPathComponent: + BSGBreadcrumbCacheFileName]; + } + } + return self; +} + +- (void)addBreadcrumb:(NSString *)breadcrumbMessage { + [self addBreadcrumbWithBlock:^(BugsnagBreadcrumb *_Nonnull crumb) { + crumb.message = breadcrumbMessage; + }]; +} + +- (void)addBreadcrumbWithBlock: + (void (^_Nonnull)(BugsnagBreadcrumb *_Nonnull))block { + if (self.capacity == 0) { + return; + } + BugsnagBreadcrumb *crumb = [BugsnagBreadcrumb breadcrumbWithBlock:block]; + if (crumb) { + [self resizeToFitCapacity:self.capacity - 1]; + dispatch_barrier_sync(self.readWriteQueue, ^{ + [self.breadcrumbs addObject:crumb]; + // Serialize crumbs to disk inside barrier to avoid simultaneous + // access to the file + if (self.cachePath != nil) { + static NSString *const arrayKeyPath = @"objectValue"; + NSArray *items = [self.breadcrumbs valueForKeyPath:arrayKeyPath]; + if ([NSJSONSerialization isValidJSONObject:items]) { + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:items + options:0 + error:&error]; + [data writeToFile:self.cachePath atomically:NO]; + if (error != nil) { + bsg_log_err(@"Failed to write breadcrumbs to disk: %@", error); + } + } + } + }); + } +} + +- (NSArray *)cachedBreadcrumbs { + __block NSArray *cache = nil; + dispatch_barrier_sync(self.readWriteQueue, ^{ + NSError *error = nil; + NSData *data = [NSData dataWithContentsOfFile:self.cachePath options:0 error:&error]; + if (error == nil) { + cache = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + } + if (error != nil) { + bsg_log_err(@"Failed to read breadcrumbs from disk: %@", error); + } + }); + return [cache isKindOfClass:[NSArray class]] ? cache : nil; +} + +@synthesize capacity = _capacity; + +- (NSUInteger)capacity { + @synchronized (self) { + return _capacity; + } +} + +- (void)setCapacity:(NSUInteger)capacity { + @synchronized (self) { + if (capacity == _capacity) { + return; + } + [self resizeToFitCapacity:capacity]; + [self willChangeValueForKey:NSStringFromSelector(@selector(capacity))]; + _capacity = MIN(100, capacity); + [self didChangeValueForKey:NSStringFromSelector(@selector(capacity))]; + } +} + +- (void)clearBreadcrumbs { + dispatch_barrier_sync(self.readWriteQueue, ^{ + [self.breadcrumbs removeAllObjects]; + }); +} + +- (NSUInteger)count { + return self.breadcrumbs.count; +} + +- (BugsnagBreadcrumb *)objectAtIndexedSubscript:(NSUInteger)index { + if (index < [self count]) { + __block BugsnagBreadcrumb *crumb = nil; + dispatch_barrier_sync(self.readWriteQueue, ^{ + crumb = self.breadcrumbs[index]; + }); + return crumb; + } + return nil; +} + +- (NSArray *)arrayValue { + if ([self count] == 0) { + return nil; + } + __block NSMutableArray *contents = + [[NSMutableArray alloc] initWithCapacity:[self count]]; + dispatch_barrier_sync(self.readWriteQueue, ^{ + for (BugsnagBreadcrumb *crumb in self.breadcrumbs) { + NSDictionary *objectValue = [crumb objectValue]; + NSError *error = nil; + @try { + if (![NSJSONSerialization isValidJSONObject:objectValue]) { + bsg_log_err(@"Unable to serialize breadcrumb: Not a valid " + @"JSON object"); + continue; + } + [contents addObject:objectValue]; + } @catch (NSException *exception) { + bsg_log_err(@"Unable to serialize breadcrumb: %@", error); + } + } + }); + return contents; +} + +- (void)resizeToFitCapacity:(NSUInteger)capacity { + if (capacity == 0) { + [self clearBreadcrumbs]; + } else if ([self count] > capacity) { + dispatch_barrier_sync(self.readWriteQueue, ^{ + [self.breadcrumbs + removeObjectsInRange:NSMakeRange(0, self.count - capacity)]; + }); + } +} + +@end diff --git a/Source/BugsnagConfiguration.m b/Source/BugsnagConfiguration.m index 75f28c09b..153efc788 100644 --- a/Source/BugsnagConfiguration.m +++ b/Source/BugsnagConfiguration.m @@ -33,6 +33,7 @@ #import "BugsnagSessionTracker.h" #import "BugsnagLogger.h" #import "BSG_SSKeychain.h" +#import "BugsnagBreadcrumbs.h" static NSString *const kHeaderApiPayloadVersion = @"Bugsnag-Payload-Version"; static NSString *const kHeaderApiKey = @"Bugsnag-Api-Key"; diff --git a/Source/BugsnagEvent.m b/Source/BugsnagEvent.m index 059890e5b..aa25e90fd 100644 --- a/Source/BugsnagEvent.m +++ b/Source/BugsnagEvent.m @@ -25,6 +25,12 @@ #import "BSG_RFC3339DateTool.h" #import "Private.h" +@interface BugsnagBreadcrumb () ++ (instancetype _Nullable)breadcrumbWithBlock: + (BSGBreadcrumbConfiguration _Nonnull)block; ++ (instancetype _Nullable)breadcrumbFromDict:(NSDictionary *_Nonnull)dict; +@end + NSMutableDictionary *BSGFormatFrame(NSDictionary *frame, NSArray *binaryImages) { NSMutableDictionary *formatted = [NSMutableDictionary dictionary]; diff --git a/Source/Private.h b/Source/Private.h index 93a9276c3..a3dbf096c 100644 --- a/Source/Private.h +++ b/Source/Private.h @@ -7,6 +7,7 @@ #import "Bugsnag.h" #import "BugsnagBreadcrumb.h" +#import "BugsnagBreadcrumbs.h" @interface BugsnagBreadcrumb () diff --git a/Tests/BugsnagBreadcrumbsTest.m b/Tests/BugsnagBreadcrumbsTest.m index 6adf8e815..b96903892 100644 --- a/Tests/BugsnagBreadcrumbsTest.m +++ b/Tests/BugsnagBreadcrumbsTest.m @@ -9,6 +9,7 @@ #import "Bugsnag.h" #import "BugsnagClient.h" #import "BugsnagBreadcrumb.h" +#import "BugsnagBreadcrumbs.h" #import "BugsnagTestConstants.h" #import @@ -16,6 +17,12 @@ @interface BugsnagBreadcrumbsTest : XCTestCase @property(nonatomic, strong) BugsnagBreadcrumbs *crumbs; @end +@interface BugsnagBreadcrumb () ++ (instancetype _Nullable)breadcrumbWithBlock: + (BSGBreadcrumbConfiguration _Nonnull)block; ++ (instancetype _Nullable)breadcrumbFromDict:(NSDictionary *_Nonnull)dict; +@end + @interface BugsnagBreadcrumbs () @property(nonatomic, readonly, strong) dispatch_queue_t readWriteQueue; @end diff --git a/UPGRADING.md b/UPGRADING.md index 26703ab1d..0c043a88b 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -166,6 +166,8 @@ The short "name" value has been removed and replaced with an arbitrarily long "m + BugsnagBreadcrumb.message ``` +`BugsnagBreadcrumbs` is no longer publicly accessible, along with `BugsnagBreadcrumb` constructors. + ### `BugsnagCrashReport` class This is now BugsnagEvent. diff --git a/iOS/Bugsnag.xcodeproj/project.pbxproj b/iOS/Bugsnag.xcodeproj/project.pbxproj index 3a798573e..8fa7049b5 100644 --- a/iOS/Bugsnag.xcodeproj/project.pbxproj +++ b/iOS/Bugsnag.xcodeproj/project.pbxproj @@ -282,6 +282,10 @@ E748DA781FD02A3F00B14909 /* BugsnagSessionFileStore.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = F42955025DBE1DCEFD928CAA /* BugsnagSessionFileStore.h */; }; E74EFDC21FD04B9200577D23 /* BugsnagSessionTrackingApiClient.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = F429517A5571A61A897E963D /* BugsnagSessionTrackingApiClient.h */; }; E77316E31F73E89E00A14F06 /* BugsnagHandledStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E77316E11F73B46600A14F06 /* BugsnagHandledStateTest.m */; }; + E77526BA242D0AE50077A42F /* BugsnagBreadcrumbs.h in Headers */ = {isa = PBXBuildFile; fileRef = E77526B8242D0AE50077A42F /* BugsnagBreadcrumbs.h */; }; + E77526BB242D0AE50077A42F /* BugsnagBreadcrumbs.m in Sources */ = {isa = PBXBuildFile; fileRef = E77526B9242D0AE50077A42F /* BugsnagBreadcrumbs.m */; }; + E77526BC242D0AE50077A42F /* BugsnagBreadcrumbs.m in Sources */ = {isa = PBXBuildFile; fileRef = E77526B9242D0AE50077A42F /* BugsnagBreadcrumbs.m */; }; + E77526BD242D0B1F0077A42F /* BugsnagBreadcrumbs.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = E77526B8242D0AE50077A42F /* BugsnagBreadcrumbs.h */; }; E784D2551FD70B3B004B01E1 /* KSCrashState_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = E784D2511FD70AE6004B01E1 /* KSCrashState_Tests.m */; }; E784D2561FD70B3E004B01E1 /* KSMach_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = E784D2521FD70AE6004B01E1 /* KSMach_Tests.m */; }; E784D25A1FD70C25004B01E1 /* KSJSONCodec_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = E784D2591FD70C25004B01E1 /* KSJSONCodec_Tests.m */; }; @@ -344,6 +348,7 @@ dstPath = "include/${PRODUCT_NAME}"; dstSubfolderSpec = 16; files = ( + E77526BD242D0B1F0077A42F /* BugsnagBreadcrumbs.h in CopyFiles */, 8A3C590923965D9400B344AA /* BugsnagPlugin.h in CopyFiles */, E79148251FD828E6003EFEBF /* BugsnagKeys.h in CopyFiles */, E79148261FD828E6003EFEBF /* BugsnagSessionTracker.h in CopyFiles */, @@ -596,6 +601,8 @@ E737DEA11F73AD7400BC7C80 /* BugsnagHandledState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BugsnagHandledState.m; path = ../Source/BugsnagHandledState.m; sourceTree = SOURCE_ROOT; }; E7397DC41F83BAC50034242A /* libBugsnagStatic.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libBugsnagStatic.a; sourceTree = BUILT_PRODUCTS_DIR; }; E77316E11F73B46600A14F06 /* BugsnagHandledStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BugsnagHandledStateTest.m; path = ../Tests/BugsnagHandledStateTest.m; sourceTree = SOURCE_ROOT; }; + E77526B8242D0AE50077A42F /* BugsnagBreadcrumbs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BugsnagBreadcrumbs.h; path = ../Source/BugsnagBreadcrumbs.h; sourceTree = ""; }; + E77526B9242D0AE50077A42F /* BugsnagBreadcrumbs.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BugsnagBreadcrumbs.m; path = ../Source/BugsnagBreadcrumbs.m; sourceTree = ""; }; E784D2511FD70AE6004B01E1 /* KSCrashState_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KSCrashState_Tests.m; path = ../Tests/KSCrash/KSCrashState_Tests.m; sourceTree = SOURCE_ROOT; }; E784D2521FD70AE6004B01E1 /* KSMach_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KSMach_Tests.m; path = ../Tests/KSCrash/KSMach_Tests.m; sourceTree = SOURCE_ROOT; }; E784D2591FD70C25004B01E1 /* KSJSONCodec_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KSJSONCodec_Tests.m; path = ../Tests/KSCrash/KSJSONCodec_Tests.m; sourceTree = SOURCE_ROOT; }; @@ -725,6 +732,8 @@ F4295E2778677786239F2B28 /* BugsnagApiClient.m */, 8A2C8F3F1C6BBE3C00846019 /* BugsnagBreadcrumb.h */, 8A2C8F401C6BBE3C00846019 /* BugsnagBreadcrumb.m */, + E77526B8242D0AE50077A42F /* BugsnagBreadcrumbs.h */, + E77526B9242D0AE50077A42F /* BugsnagBreadcrumbs.m */, 8A2C8F4B1C6BBE3C00846019 /* BugsnagClient.h */, 8A2C8F4C1C6BBE3C00846019 /* BugsnagClient.m */, 8A2C8F411C6BBE3C00846019 /* BugsnagCollections.h */, @@ -1062,6 +1071,7 @@ E7107C5C1F4C97F100BB3F98 /* BSG_KSBacktrace_Private.h in Headers */, E7107C371F4C97F100BB3F98 /* BSG_KSCrashC.h in Headers */, E7107C871F4C97F100BB3F98 /* BSG_KSCrashReportFilterCompletion.h in Headers */, + E77526BA242D0AE50077A42F /* BugsnagBreadcrumbs.h in Headers */, E7107C6F1F4C97F100BB3F98 /* BSG_KSMachApple.h in Headers */, 8A530CC022FDC3AF00F0C108 /* BSG_KSCrashIdentifier.h in Headers */, E7107C581F4C97F100BB3F98 /* BSG_KSCrashSentry_User.h in Headers */, @@ -1235,6 +1245,7 @@ 8A2C8F5E1C6BBE3C00846019 /* BugsnagClient.m in Sources */, E7107C3A1F4C97F100BB3F98 /* BSG_KSCrashDoctor.m in Sources */, E7107C421F4C97F100BB3F98 /* BSG_KSCrashState.m in Sources */, + E77526BB242D0AE50077A42F /* BugsnagBreadcrumbs.m in Sources */, E72AE1F6241A4E4400ED8972 /* BugsnagPluginClient.m in Sources */, E72BF77B1FC869F7004BE82F /* BugsnagSession.m in Sources */, 8A70D9CA22539C81006B696F /* BSGOutOfMemoryWatchdog.m in Sources */, @@ -1352,6 +1363,7 @@ E7397E3B1F83BC320034242A /* BSG_KSDynamicLinker.c in Sources */, E7397E3C1F83BC320034242A /* BSG_KSFileUtils.c in Sources */, E7397E3D1F83BC320034242A /* BSG_KSJSONCodec.c in Sources */, + E77526BC242D0AE50077A42F /* BugsnagBreadcrumbs.m in Sources */, E7397E3E1F83BC320034242A /* BSG_KSMach.c in Sources */, E72BF77C1FC869F7004BE82F /* BugsnagSession.m in Sources */, 8A70D9CB22539C81006B696F /* BSGOutOfMemoryWatchdog.m in Sources */, diff --git a/tvOS/Bugsnag.xcodeproj/project.pbxproj b/tvOS/Bugsnag.xcodeproj/project.pbxproj index 9642d8604..2befcdd8f 100644 --- a/tvOS/Bugsnag.xcodeproj/project.pbxproj +++ b/tvOS/Bugsnag.xcodeproj/project.pbxproj @@ -141,6 +141,8 @@ E76617CF1F4E459C0094CECF /* BSG_RFC3339DateTool.m in Sources */ = {isa = PBXBuildFile; fileRef = E76617631F4E459C0094CECF /* BSG_RFC3339DateTool.m */; }; E76617D01F4E459C0094CECF /* BSG_KSCrashReportFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E76617661F4E459C0094CECF /* BSG_KSCrashReportFilter.h */; }; E76617D11F4E459C0094CECF /* BSG_KSCrashReportFilterCompletion.h in Headers */ = {isa = PBXBuildFile; fileRef = E76617671F4E459C0094CECF /* BSG_KSCrashReportFilterCompletion.h */; }; + E77526C4242D0E3A0077A42F /* BugsnagBreadcrumbs.m in Sources */ = {isa = PBXBuildFile; fileRef = E77526C2242D0E3A0077A42F /* BugsnagBreadcrumbs.m */; }; + E77526C5242D0E3A0077A42F /* BugsnagBreadcrumbs.h in Headers */ = {isa = PBXBuildFile; fileRef = E77526C3242D0E3A0077A42F /* BugsnagBreadcrumbs.h */; }; E79148771FD82E6D003EFEBF /* BugsnagSession.h in Headers */ = {isa = PBXBuildFile; fileRef = E79148641FD82E6A003EFEBF /* BugsnagSession.h */; }; E79148781FD82E6D003EFEBF /* BugsnagKSCrashSysInfoParser.h in Headers */ = {isa = PBXBuildFile; fileRef = E79148651FD82E6A003EFEBF /* BugsnagKSCrashSysInfoParser.h */; }; E79148791FD82E6D003EFEBF /* BugsnagUser.h in Headers */ = {isa = PBXBuildFile; fileRef = E79148661FD82E6A003EFEBF /* BugsnagUser.h */; }; @@ -339,6 +341,8 @@ E76617631F4E459C0094CECF /* BSG_RFC3339DateTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BSG_RFC3339DateTool.m; path = ../Source/KSCrash/Source/KSCrash/Recording/Tools/BSG_RFC3339DateTool.m; sourceTree = SOURCE_ROOT; }; E76617661F4E459C0094CECF /* BSG_KSCrashReportFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BSG_KSCrashReportFilter.h; path = ../Source/KSCrash/Source/KSCrash/Reporting/Filters/BSG_KSCrashReportFilter.h; sourceTree = SOURCE_ROOT; }; E76617671F4E459C0094CECF /* BSG_KSCrashReportFilterCompletion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BSG_KSCrashReportFilterCompletion.h; path = ../Source/KSCrash/Source/KSCrash/Reporting/Filters/BSG_KSCrashReportFilterCompletion.h; sourceTree = SOURCE_ROOT; }; + E77526C2242D0E3A0077A42F /* BugsnagBreadcrumbs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BugsnagBreadcrumbs.m; path = ../Source/BugsnagBreadcrumbs.m; sourceTree = ""; }; + E77526C3242D0E3A0077A42F /* BugsnagBreadcrumbs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BugsnagBreadcrumbs.h; path = ../Source/BugsnagBreadcrumbs.h; sourceTree = ""; }; E79148641FD82E6A003EFEBF /* BugsnagSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BugsnagSession.h; path = ../Source/BugsnagSession.h; sourceTree = ""; }; E79148651FD82E6A003EFEBF /* BugsnagKSCrashSysInfoParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BugsnagKSCrashSysInfoParser.h; path = ../Source/BugsnagKSCrashSysInfoParser.h; sourceTree = ""; }; E79148661FD82E6A003EFEBF /* BugsnagUser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BugsnagUser.h; path = ../Source/BugsnagUser.h; sourceTree = ""; }; @@ -442,6 +446,8 @@ 8A8D51261D41343500D33797 /* tvOS */ = { isa = PBXGroup; children = ( + E77526C3242D0E3A0077A42F /* BugsnagBreadcrumbs.h */, + E77526C2242D0E3A0077A42F /* BugsnagBreadcrumbs.m */, E72AE1FB241A4ED600ED8972 /* BugsnagPluginClient.h */, E72AE1FC241A4ED600ED8972 /* BugsnagPluginClient.m */, 0089B6ED241168CB00D5A7F2 /* BugsnagClient.h */, @@ -802,6 +808,7 @@ E766177F1F4E459C0094CECF /* BSG_KSCrashAdvanced.h in Headers */, E76617BB1F4E459C0094CECF /* BSG_KSObjC.h in Headers */, E76617C31F4E459C0094CECF /* BSG_KSString.h in Headers */, + E77526C5242D0E3A0077A42F /* BugsnagBreadcrumbs.h in Headers */, E76617871F4E459C0094CECF /* BSG_KSCrashReportFields.h in Headers */, E76617CE1F4E459C0094CECF /* BSG_RFC3339DateTool.h in Headers */, E72352BD1F55923700436528 /* BSGConnectivity.h in Headers */, @@ -923,6 +930,7 @@ E766178E1F4E459C0094CECF /* BSG_KSCrashType.c in Sources */, E791487F1FD82E6D003EFEBF /* BugsnagKSCrashSysInfoParser.m in Sources */, E76617B51F4E459C0094CECF /* BSG_KSMach_Arm.c in Sources */, + E77526C4242D0E3A0077A42F /* BugsnagBreadcrumbs.m in Sources */, E72AE1FE241A4ED600ED8972 /* BugsnagPluginClient.m in Sources */, 8AD9A4FE1D42EE9D004E1CC5 /* BugsnagBreadcrumb.m in Sources */, 8A6C6FAD2257882400E8EF24 /* BSGOutOfMemoryWatchdog.m in Sources */,