diff --git a/.gitignore b/.gitignore index 13274926..ab6ef954 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,7 @@ Dist/ build/ build_wrapper_output_directory/ + +_ General AUL Entries Bulk Capture.txt + +_ AUL Entries Capture Samples.txt diff --git a/Demos/macosAppSwiftSPM/macosAppSwiftSPM.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Demos/macosAppSwiftSPM/macosAppSwiftSPM.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 9b8e61b4..c59da337 100644 --- a/Demos/macosAppSwiftSPM/macosAppSwiftSPM.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Demos/macosAppSwiftSPM/macosAppSwiftSPM.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -15,7 +15,7 @@ "repositoryURL": "https://github.com/microsoft/plcrashreporter.git", "state": { "branch": "master", - "revision": "2afa27e23452171b971f67730821b7befa96842b", + "revision": "b7b88ee14bbc25ce408ae05464cb6f1cdd747948", "version": null } }, @@ -24,7 +24,7 @@ "repositoryURL": "https://github.com/rollbar/rollbar-apple", "state": { "branch": "master", - "revision": "f32c08cf61692a2fbe7de5e0aedf49a1d1534683", + "revision": "50a7ef4569dd43619651c40dd11ccd16c67950b0", "version": null } } diff --git a/RollbarCommon/Sources/RollbarCommon/NSJSONSerialization+Rollbar.m b/RollbarCommon/Sources/RollbarCommon/NSJSONSerialization+Rollbar.m index 8a0b4336..3133ae1b 100644 --- a/RollbarCommon/Sources/RollbarCommon/NSJSONSerialization+Rollbar.m +++ b/RollbarCommon/Sources/RollbarCommon/NSJSONSerialization+Rollbar.m @@ -61,7 +61,7 @@ + (NSMutableDictionary *)rollbar_safeDataFromJSONObject:(id)obj { else if([obj description]) { [safeData setObject:[obj description] forKey:key]; } - } else if ([obj isKindOfClass:[NSError class]] && [obj userInfo]) { + } else if ([obj isKindOfClass:[NSError class]] && (nil != [obj userInfo])) { NSDictionary* userInfoData = [[self class] rollbar_safeDataFromJSONObject:[obj userInfo]]; if (userInfoData) { [safeData setObject:userInfoData forKey:key]; @@ -76,7 +76,7 @@ + (NSMutableDictionary *)rollbar_safeDataFromJSONObject:(id)obj { [NSJSONSerialization JSONObjectWithData:obj options:(NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves) error:&error]; - if (error == nil) { + if ((error == nil) && (nil != json)) { NSDictionary *jsonData = [[self class] rollbar_safeDataFromJSONObject:json]; if (jsonData) { [safeData setObject:jsonData forKey:key]; diff --git a/RollbarNotifier/Sources/RollbarNotifier/DTOs/RollbarCallStackFrame.m b/RollbarNotifier/Sources/RollbarNotifier/DTOs/RollbarCallStackFrame.m index 9ce90a43..e7c723fe 100644 --- a/RollbarNotifier/Sources/RollbarNotifier/DTOs/RollbarCallStackFrame.m +++ b/RollbarNotifier/Sources/RollbarNotifier/DTOs/RollbarCallStackFrame.m @@ -27,7 +27,7 @@ @implementation RollbarCallStackFrame #pragma mark - Properties -(nonnull NSString *)filename { - return [self getDataByKey:DFK_FILENAME]; + return [self safelyGetStringByKey:DFK_FILENAME];; } -(void)setFilename:(nonnull NSString *)value { diff --git a/RollbarNotifier/Sources/RollbarNotifier/DTOs/RollbarData.m b/RollbarNotifier/Sources/RollbarNotifier/DTOs/RollbarData.m index b5d7c3da..f2a1fb59 100644 --- a/RollbarNotifier/Sources/RollbarNotifier/DTOs/RollbarData.m +++ b/RollbarNotifier/Sources/RollbarNotifier/DTOs/RollbarData.m @@ -43,7 +43,7 @@ @implementation RollbarData #pragma mark - properties - (NSString *)environment { - return [self getDataByKey:DFK_ENVIRONMENT]; + return [self safelyGetStringByKey:DFK_ENVIRONMENT]; } - (void)setEnvironment:(NSString *)environment { @@ -63,7 +63,7 @@ -(void)setBody:(nonnull RollbarBody *)value { } -(RollbarLevel)level { - NSString *result = [self getDataByKey:DFK_LEVEL]; + NSString *result = [self safelyGetStringByKey:DFK_LEVEL]; return [RollbarLevelUtil RollbarLevelFromString:result]; } @@ -85,7 +85,7 @@ -(void)setTimestamp:(NSTimeInterval)value { } -(NSString *)codeVersion { - NSString *result = [self getDataByKey:DFK_CODE_VERSION]; + NSString *result = [self safelyGetStringByKey:DFK_CODE_VERSION]; return result; } @@ -103,7 +103,7 @@ -(void)setPlatform:(NSString *)value { } -(RollbarAppLanguage)language { - NSString *result = [self getDataByKey:DFK_LANGUAGE]; + NSString *result = [self safelyGetStringByKey:DFK_LANGUAGE]; return [RollbarAppLanguageUtil RollbarAppLanguageFromString:result]; } diff --git a/RollbarNotifier/Sources/RollbarNotifier/RollbarAulLogLevelConverter.m b/RollbarNotifier/Sources/RollbarNotifier/RollbarAulLogLevelConverter.m new file mode 100644 index 00000000..5f239213 --- /dev/null +++ b/RollbarNotifier/Sources/RollbarNotifier/RollbarAulLogLevelConverter.m @@ -0,0 +1,44 @@ +// +// RollbarAulLogLevelConverter.m +// +// +// Created by Andrey Kornich on 2021-03-24. +// + +#import "RollbarAulLogLevelConverter.h" + +@implementation RollbarAulLogLevelConverter + ++ (os_log_type_t) RollbarLevelToAulLevel:(RollbarLevel)value { + + switch (value) { + case RollbarLevel_Debug: + return OS_LOG_TYPE_DEBUG; + case RollbarLevel_Info: + return OS_LOG_TYPE_INFO; + case RollbarLevel_Warning: + return OS_LOG_TYPE_DEFAULT; + case RollbarLevel_Error: + return OS_LOG_TYPE_ERROR; + case RollbarLevel_Critical: + return OS_LOG_TYPE_FAULT; + } +} + ++ (RollbarLevel) RollbarLevelFromAulLevel:(os_log_type_t)value { + + switch (value) { + case OS_LOG_TYPE_DEBUG: + return RollbarLevel_Debug; + case OS_LOG_TYPE_INFO: + return RollbarLevel_Info; + case OS_LOG_TYPE_ERROR: + return RollbarLevel_Error; + case OS_LOG_TYPE_FAULT: + return RollbarLevel_Critical; + case OS_LOG_TYPE_DEFAULT: + return RollbarLevel_Warning; + } +} + +@end diff --git a/RollbarNotifier/Sources/RollbarNotifier/RollbarAulOSLogEntryLogLevelConverter.m b/RollbarNotifier/Sources/RollbarNotifier/RollbarAulOSLogEntryLogLevelConverter.m new file mode 100644 index 00000000..a7520a23 --- /dev/null +++ b/RollbarNotifier/Sources/RollbarNotifier/RollbarAulOSLogEntryLogLevelConverter.m @@ -0,0 +1,66 @@ +// +// RollbarAulOSLogEntryLogLevelConverter.m +// +// +// Created by Andrey Kornich on 2021-03-24. +// + +#import "RollbarAulOSLogEntryLogLevelConverter.h" + +@implementation RollbarAulOSLogEntryLogLevelConverter + ++ (OSLogEntryLogLevel) RollbarLevelToOSLogEntryLogLevel:(RollbarLevel)value { + + switch (value) { + + case RollbarLevel_Debug: + return OSLogEntryLogLevelDebug; + case RollbarLevel_Info: + return OSLogEntryLogLevelInfo; + case RollbarLevel_Warning: + return OSLogEntryLogLevelNotice; + case RollbarLevel_Error: + return OSLogEntryLogLevelError; + case RollbarLevel_Critical: + return OSLogEntryLogLevelFault; + } +} + ++ (RollbarLevel) RollbarLevelFromOSLogEntryLogLevel:(OSLogEntryLogLevel)value { + + switch (value) { + + case OSLogEntryLogLevelUndefined: + case OSLogEntryLogLevelDebug: + return RollbarLevel_Debug; + case OSLogEntryLogLevelInfo: + return RollbarLevel_Info; + case OSLogEntryLogLevelNotice: + return RollbarLevel_Warning; + case OSLogEntryLogLevelError: + return RollbarLevel_Error; + case OSLogEntryLogLevelFault: + return RollbarLevel_Critical; + } +} + ++ (NSString *) OSLogEntryLogLevelToString:(OSLogEntryLogLevel)value { + + switch (value) { + + case OSLogEntryLogLevelUndefined: + return @"OSLogEntryLogLevelUndefined"; + case OSLogEntryLogLevelDebug: + return @"OSLogEntryLogLevelDebug"; + case OSLogEntryLogLevelInfo: + return @"OSLogEntryLogLevelInfo"; + case OSLogEntryLogLevelNotice: + return @"OSLogEntryLogLevelNotice"; + case OSLogEntryLogLevelError: + return @"OSLogEntryLogLevelError"; + case OSLogEntryLogLevelFault: + return @"OSLogEntryLogLevelFault"; + } +} + +@end diff --git a/RollbarNotifier/Sources/RollbarNotifier/include/RollbarAulLogLevelConverter.h b/RollbarNotifier/Sources/RollbarNotifier/include/RollbarAulLogLevelConverter.h new file mode 100644 index 00000000..f2a2d013 --- /dev/null +++ b/RollbarNotifier/Sources/RollbarNotifier/include/RollbarAulLogLevelConverter.h @@ -0,0 +1,23 @@ +// +// RollbarAulLogLevelConverter.h +// +// +// Created by Andrey Kornich on 2021-03-24. +// + +@import Foundation; +@import OSLog; + +#import "RollbarLevel.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface RollbarAulLogLevelConverter : NSObject + ++ (os_log_type_t) RollbarLevelToAulLevel:(RollbarLevel)value; + ++ (RollbarLevel) RollbarLevelFromAulLevel:(os_log_type_t)value; + +@end + +NS_ASSUME_NONNULL_END diff --git a/RollbarNotifier/Sources/RollbarNotifier/include/RollbarAulOSLogEntryLogLevelConverter.h b/RollbarNotifier/Sources/RollbarNotifier/include/RollbarAulOSLogEntryLogLevelConverter.h new file mode 100644 index 00000000..fc37831d --- /dev/null +++ b/RollbarNotifier/Sources/RollbarNotifier/include/RollbarAulOSLogEntryLogLevelConverter.h @@ -0,0 +1,27 @@ +// +// RollbarAulOSLogEntryLogLevelConverter.h +// +// +// Created by Andrey Kornich on 2021-03-24. +// + +@import Foundation; +@import OSLog; + +#import "RollbarLevel.h" + +NS_ASSUME_NONNULL_BEGIN + +API_AVAILABLE(macos(10.15)) +API_UNAVAILABLE(ios, tvos, watchos) +@interface RollbarAulOSLogEntryLogLevelConverter : NSObject + ++ (OSLogEntryLogLevel) RollbarLevelToOSLogEntryLogLevel:(RollbarLevel)value; + ++ (RollbarLevel) RollbarLevelFromOSLogEntryLogLevel:(OSLogEntryLogLevel)value; + ++ (NSString *) OSLogEntryLogLevelToString:(OSLogEntryLogLevel)value; + +@end + +NS_ASSUME_NONNULL_END diff --git a/RollbarNotifier/Tests/RollbarNotifierTests-ObjC/RollbarAulLogLevelConverterTests.m b/RollbarNotifier/Tests/RollbarNotifierTests-ObjC/RollbarAulLogLevelConverterTests.m new file mode 100644 index 00000000..f5e95009 --- /dev/null +++ b/RollbarNotifier/Tests/RollbarNotifierTests-ObjC/RollbarAulLogLevelConverterTests.m @@ -0,0 +1,67 @@ +@import Foundation; +@import OSLog; +@import RollbarNotifier; + +#if !TARGET_OS_WATCH +#import + +@import RollbarNotifier; + +@interface RollbarAulLogLevelConverterTests : XCTestCase + +@end + +@implementation RollbarAulLogLevelConverterTests + +- (void)setUp { + [super setUp]; +} + +- (void)tearDown { + [super tearDown]; +} + +- (NSArray *) getOrederedAulLevels { + + return @[ + + [NSNumber numberWithUnsignedShort:OS_LOG_TYPE_DEBUG], + [NSNumber numberWithUnsignedShort:OS_LOG_TYPE_INFO], + [NSNumber numberWithUnsignedShort:OS_LOG_TYPE_DEFAULT], + [NSNumber numberWithUnsignedShort:OS_LOG_TYPE_ERROR], + [NSNumber numberWithUnsignedShort:OS_LOG_TYPE_FAULT] + ]; +} + +- (NSArray *) getOrederedRollbarLevels { + + return @[ + + [NSNumber numberWithUnsignedLong:RollbarLevel_Debug], + [NSNumber numberWithUnsignedLong:RollbarLevel_Info], + [NSNumber numberWithUnsignedLong:RollbarLevel_Warning], + [NSNumber numberWithUnsignedLong:RollbarLevel_Error], + [NSNumber numberWithUnsignedLong:RollbarLevel_Critical] + ]; +} + +- (void)testRollbarLevelFromAulLevel { + + XCTAssertEqual(RollbarLevel_Debug, [RollbarAulLogLevelConverter RollbarLevelFromAulLevel:OS_LOG_TYPE_DEBUG]); + XCTAssertEqual(RollbarLevel_Info, [RollbarAulLogLevelConverter RollbarLevelFromAulLevel:OS_LOG_TYPE_INFO]); + XCTAssertEqual(RollbarLevel_Warning, [RollbarAulLogLevelConverter RollbarLevelFromAulLevel:OS_LOG_TYPE_DEFAULT]); + XCTAssertEqual(RollbarLevel_Error, [RollbarAulLogLevelConverter RollbarLevelFromAulLevel:OS_LOG_TYPE_ERROR]); + XCTAssertEqual(RollbarLevel_Critical, [RollbarAulLogLevelConverter RollbarLevelFromAulLevel:OS_LOG_TYPE_FAULT]); +} + +- (void)testRollbarLevelToAulLevel { + + XCTAssertEqual(OS_LOG_TYPE_DEBUG, [RollbarAulLogLevelConverter RollbarLevelToAulLevel:RollbarLevel_Debug]); + XCTAssertEqual(OS_LOG_TYPE_INFO, [RollbarAulLogLevelConverter RollbarLevelToAulLevel:RollbarLevel_Info]); + XCTAssertEqual(OS_LOG_TYPE_DEFAULT, [RollbarAulLogLevelConverter RollbarLevelToAulLevel:RollbarLevel_Warning]); + XCTAssertEqual(OS_LOG_TYPE_ERROR, [RollbarAulLogLevelConverter RollbarLevelToAulLevel:RollbarLevel_Error]); + XCTAssertEqual(OS_LOG_TYPE_FAULT, [RollbarAulLogLevelConverter RollbarLevelToAulLevel:RollbarLevel_Critical]); +} + +@end +#endif diff --git a/RollbarNotifier/Tests/RollbarNotifierTests-ObjC/RollbarAulOSLogEntryLogLevelConverterTests.m b/RollbarNotifier/Tests/RollbarNotifierTests-ObjC/RollbarAulOSLogEntryLogLevelConverterTests.m new file mode 100644 index 00000000..a88ec1d5 --- /dev/null +++ b/RollbarNotifier/Tests/RollbarNotifierTests-ObjC/RollbarAulOSLogEntryLogLevelConverterTests.m @@ -0,0 +1,55 @@ +@import Foundation; +@import OSLog; +@import RollbarNotifier; + +#if !TARGET_OS_WATCH +#import + +@import RollbarNotifier; + +@interface RollbarAulOSLogEntryLogLevelConverterTests : XCTestCase + +@end + +@implementation RollbarAulOSLogEntryLogLevelConverterTests + +- (void)setUp { + [super setUp]; +} + +- (void)tearDown { + [super tearDown]; +} + +- (void)testRollbarLevelFromOSLogEntryLogLevel { + + XCTAssertEqual(RollbarLevel_Debug, + [RollbarAulOSLogEntryLogLevelConverter RollbarLevelFromOSLogEntryLogLevel:OSLogEntryLogLevelUndefined]); + XCTAssertEqual(RollbarLevel_Debug, + [RollbarAulOSLogEntryLogLevelConverter RollbarLevelFromOSLogEntryLogLevel:OSLogEntryLogLevelDebug]); + XCTAssertEqual(RollbarLevel_Info, + [RollbarAulOSLogEntryLogLevelConverter RollbarLevelFromOSLogEntryLogLevel:OSLogEntryLogLevelInfo]); + XCTAssertEqual(RollbarLevel_Warning, + [RollbarAulOSLogEntryLogLevelConverter RollbarLevelFromOSLogEntryLogLevel:OSLogEntryLogLevelNotice]); + XCTAssertEqual(RollbarLevel_Error, + [RollbarAulOSLogEntryLogLevelConverter RollbarLevelFromOSLogEntryLogLevel:OSLogEntryLogLevelError]); + XCTAssertEqual(RollbarLevel_Critical, + [RollbarAulOSLogEntryLogLevelConverter RollbarLevelFromOSLogEntryLogLevel:OSLogEntryLogLevelFault]); +} + +- (void)testRollbarLevelToOSLogEntryLogLevel { + + XCTAssertEqual(OSLogEntryLogLevelDebug, + [RollbarAulOSLogEntryLogLevelConverter RollbarLevelToOSLogEntryLogLevel:RollbarLevel_Debug]); + XCTAssertEqual(OSLogEntryLogLevelInfo, + [RollbarAulOSLogEntryLogLevelConverter RollbarLevelToOSLogEntryLogLevel:RollbarLevel_Info]); + XCTAssertEqual(OSLogEntryLogLevelNotice, + [RollbarAulOSLogEntryLogLevelConverter RollbarLevelToOSLogEntryLogLevel:RollbarLevel_Warning]); + XCTAssertEqual(OSLogEntryLogLevelError, + [RollbarAulOSLogEntryLogLevelConverter RollbarLevelToOSLogEntryLogLevel:RollbarLevel_Error]); + XCTAssertEqual(OSLogEntryLogLevelFault, + [RollbarAulOSLogEntryLogLevelConverter RollbarLevelToOSLogEntryLogLevel:RollbarLevel_Critical]); +} + +@end +#endif diff --git a/RollbarNotifier/Tests/RollbarNotifierTests-ObjC/RollbarAulTests.m b/RollbarNotifier/Tests/RollbarNotifierTests-ObjC/RollbarAulTests.m new file mode 100644 index 00000000..56c27a23 --- /dev/null +++ b/RollbarNotifier/Tests/RollbarNotifierTests-ObjC/RollbarAulTests.m @@ -0,0 +1,415 @@ +@import Foundation; +@import OSLog; + +#if !TARGET_OS_WATCH +#import + +@import RollbarNotifier; + +@interface RollbarAulTests : XCTestCase + +@end + +@implementation RollbarAulTests + +- (void)setUp { + [super setUp]; +} + +- (void)tearDown { + [super tearDown]; +} + +- (void)testSampleAULEntries { + + NSDate *date = [[NSDate date] dateByAddingTimeInterval:-3.0]; + + [self traceTimestamp:date]; + + NSError *error = nil; + OSLogStore *logStore = [OSLogStore localStoreAndReturnError:&error]; + if (nil != error) { + NSLog(@"AUL ERROR: %@", error); + } + + OSLogPosition *logPosition = [logStore positionWithDate:date]; + + OSLogEnumerator *logEnumerator = [self buildAulLogEnumeratorWithinLogStore:logStore + staringAtPosition:logPosition + forSubsystem:nil //@"com.your_company.your_subsystem" + andForCategory:nil]; //@"your_category_name"]; + int count = [self processLogEntries:logEnumerator]; + NSLog(@"Total AUL entries: %d", count); +} + +- (void)testAUL { + + NSDate *date = [[NSDate date] dateByAddingTimeInterval:-1.0]; + + [self traceTimestamp:date]; + + // Log a message to the default log and default log level.os_log(OS_LOG_DEFAULT, "This is a default message."); + + // Log a message to the default log and debug log level + os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_DEBUG, "This is a debug message."); + + // Log an error to a custom log object. + os_log_t customLog = os_log_create("com.your_company.your_subsystem", "your_category_name"); + int i = 0; + int maxIterations = 4; + while (i++ < maxIterations) { + NSDateFormatter *timestampFormatter = [[NSDateFormatter alloc] init]; + [timestampFormatter setDateFormat:@"YYYY-MM-dd 'at' HH:mm:ss.SSSSSSXX"]; + //NSString *msg = [NSString stringWithFormat:@"An error occurred at %@!", [timestampFormatter stringFromDate:[NSDate date]] ]; + os_log_error(customLog, "An error occurred at %@!", [timestampFormatter stringFromDate:[NSDate date]]); + os_log_debug(customLog, "An error occurred at %@!", [timestampFormatter stringFromDate:[NSDate date]]); + NSLog(@"Test NSLog"); + } + +// LEGACY WORKING VERSION: +// NSError *error = nil; +// id osLogStore = [OSLogStore localStoreAndReturnError:&error]; +// if (nil != error) { +// NSLog(@"AUL ERROR: %@", error); +// } +// +// //[NSThread sleepForTimeInterval:1.0f]; +// +// OSLogPosition *logPosition = [osLogStore positionWithDate:date]; +// //NSTimeInterval timeInterval = 3.0; +// //OSLogPosition *logPosition = [osLogStore positionWithTimeIntervalSinceEnd:timeInterval]; +// +// //NSPredicate *datePredicate = [NSPredicate predicateWithFormat:@"(date >= %@) AND (date <= %@)", startDate, endDate]; +// //NSPredicate *datePredicate = [NSPredicate predicateWithFormat:@"date >= %@", date]; +// NSPredicate *subsystemPredicate = [NSPredicate predicateWithFormat:@"subsystem == %@", @"com.your_company.your_subsystem"]; +// NSPredicate *categoryPredicate = [NSPredicate predicateWithFormat:@"category == %@", @"your_category_name"]; +// NSPredicate *levelPredicate = [NSPredicate predicateWithFormat:@"level == %@", [NSNumber numberWithUnsignedInteger:OS_LOG_TYPE_DEFAULT] ]; +// //NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[levelPredicate, subsystemPredicate, categoryPredicate]]; +// NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[subsystemPredicate, categoryPredicate]]; +// +// //[NSThread sleepForTimeInterval:1.0f]; +// +// OSLogEnumerator *logEnumerator = [osLogStore entriesEnumeratorWithOptions:0 +// position:logPosition +// predicate:predicate +// error:&error]; +// if (nil != error) { +// NSLog(@"AUL ERROR: %@", error); +// } +// +// //[NSThread sleepForTimeInterval:1.0f]; +// +// //NSUInteger count = logEnumerator.allObjects.count; +// int count = 0; +// for (OSLogEntryLog *entry in logEnumerator) { +// +// NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; +// [formatter setDateFormat:@"YYYY-MM-dd 'at' HH:mm:ss.SSSSSSXX"]; +// NSLog(@">>>>> %@: %@", [formatter stringFromDate:entry.date], entry.composedMessage); +// count++; +// } +// NSLog(@"LEGACY Total AUL entries: %d", count); + +// NEW MORE STRUCTURED IMPLEMENTATION: + NSError *error = nil; + OSLogStore *logStore = [OSLogStore localStoreAndReturnError:&error]; + if (nil != error) { + NSLog(@"AUL ERROR: %@", error); + } + + OSLogPosition *logPosition = [logStore positionWithDate:date]; + + OSLogEnumerator *logEnumerator = [self buildAulLogEnumeratorWithinLogStore:logStore + staringAtPosition:logPosition + forSubsystem:@"com.your_company.your_subsystem" + andForCategory:@"your_category_name"]; + int count = [self processLogEntries:logEnumerator]; + NSLog(@"Total AUL entries: %d", count); + //XCTAssertEqual(count, 2 * maxIterations); +} + +#pragma mark - RollbarNotifier RollbarAulEntrySnapper + +// make it public +- (void)captureOSLogEntry:(nullable OSLogEntry *)entry + intoSnapshot:(nonnull NSMutableDictionary *)snapshot { + + if (nil == entry) { + return; + } + + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"YYYY-MM-dd 'at' HH:mm:ss.SSSSSSXX"]; + + snapshot[@"date"] = [formatter stringFromDate:entry.date]; + snapshot[@"className"] = entry.className; + snapshot[@"composedMessage"] = entry.composedMessage; + //snapShot[@""] = entry.storeCategory; + + if ([entry isKindOfClass:[OSLogEntryLog class]]) { + + [self captureOSLogEntryLog:(OSLogEntryLog *)entry + intoSnapshot:snapshot]; + } + else if ([entry isKindOfClass:[OSLogEntryActivity class]]) { + + [self captureOSLogEntryActivity:(OSLogEntryActivity *)entry + intoSnapshot:snapshot]; + } + else if ([entry isKindOfClass:[OSLogEntrySignpost class]]) { + + [self captureOSLogEntrySignpost:(OSLogEntrySignpost *)entry + intoSnapshot:snapshot]; + } + else if ([entry conformsToProtocol:@protocol(OSLogEntryFromProcess)]) { + + [self captureOSLogEntryFromProcess:(OSLogEntry *)entry + intoSnapshot:snapshot]; + } + else if ([entry conformsToProtocol:@protocol(OSLogEntryWithPayload)]) { + + [self captureOSLogEntryWithPayload:(OSLogEntry *)entry + intoSnapshot:snapshot]; + } +} + +// make it private +- (void)captureOSLogEntryLog:(nullable OSLogEntryLog *)entry + intoSnapshot:(nonnull NSMutableDictionary *)snapshot { + + if (nil == entry) { + return; + } + + snapshot[@"level"] = [RollbarAulOSLogEntryLogLevelConverter OSLogEntryLogLevelToString:entry.level]; +} + +// make it private +- (void)captureOSLogEntryActivity:(nullable OSLogEntryActivity *)entry + intoSnapshot:(nonnull NSMutableDictionary *)snapshot { + + if (nil == entry) { + return; + } + + snapshot[@"parentActivityIdentifier"] = [NSNumber numberWithUnsignedInt:entry.parentActivityIdentifier]; +} + +// make it private +- (void)captureOSLogEntrySignpost:(nullable OSLogEntrySignpost *)entry + intoSnapshot:(nonnull NSMutableDictionary *)snapshot { + + if (nil == entry) { + return; + } + + snapshot[@"signpostIdentifier"] = [NSNumber numberWithUnsignedInt:entry.signpostIdentifier]; + snapshot[@"signpostName"] = entry.signpostName; + snapshot[@"signpostType"] = [NSNumber numberWithInteger:entry.signpostType]; +} + +// make it private +- (void)captureOSLogEntryFromProcess:(nullable OSLogEntry *)entry + intoSnapshot:(nonnull NSMutableDictionary *)snapshot { + + if (nil == entry) { + return; + } + + snapshot[@"activityIdentifier"] = [NSNumber numberWithUnsignedInt:entry.activityIdentifier]; //uint64 + snapshot[@"process"] = entry.process; + snapshot[@"processIdentifier"] = [NSNumber numberWithInt:entry.processIdentifier]; + snapshot[@"sender"] = entry.sender; + snapshot[@"threadIdentifier"] = [NSNumber numberWithUnsignedInt:entry.threadIdentifier]; +} + +// make it private +- (void)captureOSLogEntryWithPayload:(nullable OSLogEntry *)entry + intoSnapshot:(nonnull NSMutableDictionary *)snapshot { + + if (nil == entry) { + return; + } + + snapshot[@"category"] = entry.category; + snapshot[@"subsystem"] = entry.subsystem; +} + + +#pragma mark - RollbarNotifier RollbarAulClient + +- (int)processLogEntries:(OSLogEnumerator *)logEnumerator { + + int count = 0; + for (OSLogEntryLog *entry in logEnumerator) { + + //TODO: reimplement to forward the log entries to Rollbar!!! + +// NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; +// [formatter setDateFormat:@"YYYY-MM-dd 'at' HH:mm:ss.SSSSSSXX"]; +// NSLog(@">>>>> %@: %@", [formatter stringFromDate:entry.date], entry.composedMessage); + + NSLog(@""); + NSLog(@"=== START AUL ENTRY ==="); + NSMutableDictionary *entrySnapshot = [NSMutableDictionary dictionaryWithCapacity:20]; + [self captureOSLogEntry:entry intoSnapshot:entrySnapshot]; + for (NSString *key in entrySnapshot) { + id value = entrySnapshot[key]; + NSLog(@" %@: %@", key, value); + } + NSLog(@"=== END AUL ENTRY ==="); + NSLog(@""); + + count++; + } + return count; +} + +- (nullable OSLogEnumerator *)buildAulLogEnumeratorWithinLogStore:(nullable OSLogStore *)logStore + staringAtPosition:(nullable OSLogPosition *)logPosition + forSubsystem:(nullable NSString *)subsystem + andForCategory:(nullable NSString *)category { + + if (nil == logStore) { + + return nil; + } + + NSPredicate *predicate = [self buildRollbarAulPredicateForSubsystem:subsystem + andForCategory:category]; + + NSError *error = nil; + OSLogEnumerator *logEnumerator = [logStore entriesEnumeratorWithOptions:0 + position:logPosition + predicate:predicate + error:&error]; + if (nil != error) { + + //TODO: log into the SDK log + return nil; + } + + return logEnumerator; +} + +#pragma mark - RollbarNotifier RollbarAulPredicateBuilder + +- (nullable NSPredicate *)buildRollbarAulPredicateForSubsystem:(nullable NSString *)subsystem + andForCategory:(nullable NSString *)category { + + NSPredicate *subsystemPredicate = [self buildSubsystemPredicate:subsystem]; + NSPredicate *categoryPredicate = [self buildCategoryPredicate:category]; + + if ((nil != subsystemPredicate) && (nil != categoryPredicate)) { + + NSPredicate *predicate = + [NSCompoundPredicate andPredicateWithSubpredicates:@[subsystemPredicate, categoryPredicate]]; + return predicate; + } + else if (nil != subsystemPredicate) { + + return subsystemPredicate; + } + else if (nil != categoryPredicate) { + + return categoryPredicate; + } + else { + return nil; + } +} + +- (nullable NSPredicate *)buildSubsystemPredicate:(nullable NSString *)subsystem { + + NSPredicate *predicate = nil; + + if (nil != subsystem) { + + //predicate = [NSPredicate predicateWithFormat:@"subsystem == %@", subsystem]; + + predicate = [self buildStringPredicateWithValue:subsystem + forProperty:@"subsystem"]; + } + + return predicate; +} + +- (nullable NSPredicate *)buildCategoryPredicate:(nullable NSString *)category { + + NSPredicate *predicate = nil; + + if (nil != category) { + + //predicate = [NSPredicate predicateWithFormat:@"category == %@", category]; + + predicate = [self buildStringPredicateWithValue:category + forProperty:@"category"]; + } + + return predicate; +} + +- (nullable NSPredicate *)buildInclusiveTimeIntervalPredicateStartingAt:(nullable NSDate *)startTime + endingAt:(nullable NSDate *)endTime { + + NSPredicate *predicate = [self buildInclusiveTimeIntervalPredicateStartingAt:startTime + endingAt:endTime + forProperty:@"data"]; + return predicate; +} + +#pragma mark - RollbarCommon RollbarPredicateBuilder + +- (nullable NSPredicate *)buildStringPredicateWithValue:(nullable NSString *)value + forProperty:(nullable NSString *)property { + + NSPredicate *predicate = nil; + + if ((nil != property) && (nil != value)) { + + predicate = [NSPredicate predicateWithFormat:@"%K == %@", property, value]; + } + else if (nil != property) { + + predicate = [NSPredicate predicateWithFormat:@"%K == nil", property, value]; + } + + return predicate; +} + +- (nullable NSPredicate *)buildInclusiveTimeIntervalPredicateStartingAt:(nullable NSDate *)startTime + endingAt:(nullable NSDate *)endTime + forProperty:(nullable NSString *)property { + + if (nil == property) { + + return nil; + } + + NSPredicate *predicate = nil; + + if ((nil != startTime) && (nil != endTime)) { + + predicate = [NSPredicate predicateWithFormat:@"(date >= %@) AND (date <= %@)", startTime, endTime]; + } + else if (nil != startTime) { + + predicate = [NSPredicate predicateWithFormat:@"date >= %@", startTime]; + } + else if (nil != endTime) { + + predicate = [NSPredicate predicateWithFormat:@"date <= %@", endTime]; + } + + return predicate; +} + +- (void)traceTimestamp:(nonnull NSDate *)timestamp { + + NSDateFormatter *timestampFormatter = [[NSDateFormatter alloc] init]; + [timestampFormatter setDateFormat:@"YYYY-MM-dd 'at' HH:mm:ss.SSSSSSXX"]; + NSLog(@">>>>> Timestamp: %@", [timestampFormatter stringFromDate:timestamp]); +} + +@end +#endif