You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
// // FLEXASLLogController.m // FLEX // // Created by Tanner on 3/14/19. // Copyright © 2019 Flipboard. All rights reserved. //
#import "FLEXASLLogController.h" #import <asl.h>
// Querrying the ASL is much slower in the simulator. We need a longer polling interval to keep things repsonsive. #if TARGET_IPHONE_SIMULATOR #define updateInterval 5.0 #else #define updateInterval 1.0 #endif
@interface FLEXASLLogController ()
@property (nonatomic, readonly) void (^updateHandler)(NSArray<FLEXSystemLogMessage *> *);
@property (nonatomic, strong) NSTimer *logUpdateTimer; @property (nonatomic, readonly) NSMutableIndexSet *logMessageIdentifiers;
// ASL stuff
@property (nonatomic) NSUInteger heapSize; @property (nonatomic) dispatch_queue_t logQueue; @property (nonatomic) dispatch_io_t io; @property (nonatomic) NSString *remaining; @property (nonatomic) int stderror; @property (nonatomic) NSString *lastTimestamp;
@end
@implementation FLEXASLLogController
+ (instancetype)withUpdateHandler:(void(^)(NSArray<FLEXSystemLogMessage *> *newMessages))newMessagesHandler { return [[self alloc] initWithUpdateHandler:newMessagesHandler]; }
- (id)initWithUpdateHandler:(void(^)(NSArray<FLEXSystemLogMessage *> *newMessages))newMessagesHandler { NSParameterAssert(newMessagesHandler);
self = [super init]; if (self) { _updateHandler = newMessagesHandler; _logMessageIdentifiers = [NSMutableIndexSet indexSet]; self.logUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:updateInterval target:self selector:@selector(updateLogMessages) userInfo:nil repeats:YES]; }
return self; }
- (void)dealloc { [self.logUpdateTimer invalidate]; }
- (BOOL)startMonitoring { [self.logUpdateTimer fire]; return YES; }
- (void)updateLogMessages { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSArray<FLEXSystemLogMessage *> *newMessages; @synchronized (self) { newMessages = [self newLogMessagesForCurrentProcess]; if (!newMessages.count) { return; }
for (FLEXSystemLogMessage *message in newMessages) { [self.logMessageIdentifiers addIndex:(NSUInteger)message.messageID]; }
self.lastTimestamp = @(asl_get(newMessages.lastObject.aslMessage, ASL_KEY_TIME) ?: "null"); }
dispatch_async(dispatch_get_main_queue(), ^{ self.updateHandler(newMessages); }); }); }
#pragma mark - Log Message Fetching
- (NSArray<FLEXSystemLogMessage *> *)newLogMessagesForCurrentProcess { if (!self.logMessageIdentifiers.count) { return [self allLogMessagesForCurrentProcess]; }
aslresponse response = [self ASLMessageListForCurrentProcess]; aslmsg aslMessage = NULL;
NSMutableArray<FLEXSystemLogMessage *> *newMessages = [NSMutableArray array];
while ((aslMessage = asl_next(response))) { NSUInteger messageID = (NSUInteger)atoll(asl_get(aslMessage, ASL_KEY_MSG_ID)); if (![self.logMessageIdentifiers containsIndex:messageID]) { [newMessages addObject:[FLEXSystemLogMessage logMessageFromASLMessage:aslMessage]]; } }
asl_release(response); return newMessages; }
- (aslresponse)ASLMessageListForCurrentProcess { static NSString *pidString = nil; if (!pidString) { pidString = @([[NSProcessInfo processInfo] processIdentifier]).stringValue; }
// Create system log query object. asl_object_t query = asl_new(ASL_TYPE_QUERY);
// Filter for messages from the current process. // Note that this appears to happen by default on device, but is required in the simulator. asl_set_query(query, ASL_KEY_PID, pidString.UTF8String, ASL_QUERY_OP_EQUAL); // Filter for messages after the last retreived message. if (self.lastTimestamp) { asl_set_query(query, ASL_KEY_TIME, self.lastTimestamp.UTF8String, ASL_QUERY_OP_GREATER); }
return asl_search(NULL, query); }
- (NSArray<FLEXSystemLogMessage *> *)allLogMessagesForCurrentProcess { aslresponse response = [self ASLMessageListForCurrentProcess]; aslmsg aslMessage = NULL;
NSMutableArray<FLEXSystemLogMessage *> *logMessages = [NSMutableArray array]; while ((aslMessage = asl_next(response))) { [logMessages addObject:[FLEXSystemLogMessage logMessageFromASLMessage:aslMessage]]; } asl_release(response);
return logMessages; }
@end
|