Skip to content

Instantly share code, notes, and snippets.

@nevyn
Created November 30, 2015 23:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nevyn/f2a85247391ff43c72da to your computer and use it in GitHub Desktop.
Save nevyn/f2a85247391ff43c72da to your computer and use it in GitHub Desktop.
Capturing ASL on Mac/iOS
// See also https://github.com/CocoaLumberjack/CocoaLumberjack/blob/master/Classes/DDASLLogCapture.m
#import "GFASLProxy.h"
#include <asl.h>
#include <notify.h>
#include <notify_keys.h>
#include <sys/time.h>
@implementation GFASLProxy
{
unsigned long long _lastSeenID;
int _notifyToken;
unsigned long long _startTime;
}
- (id)init
{
if(!(self = [super init]))
return nil;
struct timeval timeval = {
.tv_sec = 0
};
gettimeofday(&timeval, NULL);
_startTime = timeval.tv_sec;
__weak typeof(self) weakSelf = self;
notify_register_dispatch(kNotifyASLDBUpdate, &_notifyToken, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(int token)
{
[weakSelf _lookForNewMessages];
});
return self;
}
- (void)dealloc
{
notify_cancel(_notifyToken);
}
- (void)_lookForNewMessages
{
aslmsg query = asl_new(ASL_TYPE_QUERY);
char stringValue[64];
if (_lastSeenID > 0) {
snprintf(stringValue, sizeof stringValue, "%llu", _lastSeenID);
asl_set_query(query, ASL_KEY_MSG_ID, stringValue, ASL_QUERY_OP_GREATER | ASL_QUERY_OP_NUMERIC);
} else {
snprintf(stringValue, sizeof stringValue, "%llu", _startTime);
asl_set_query(query, ASL_KEY_TIME, stringValue, ASL_QUERY_OP_GREATER_EQUAL | ASL_QUERY_OP_NUMERIC);
}
const char param[] = "7"; // ASL_LEVEL_DEBUG
asl_set_query(query, ASL_KEY_LEVEL, param, ASL_QUERY_OP_LESS_EQUAL | ASL_QUERY_OP_NUMERIC);
// Iterate over new messages.
aslmsg msg;
aslresponse response = asl_search(NULL, query);
while ((msg = asl_next(response)))
{
[self _messageReceived:msg];
// Keep track of which messages we've seen.
_lastSeenID = atoll(asl_get(msg, ASL_KEY_MSG_ID));
}
asl_release(response);
free(query);
}
- (void)_messageReceived:(aslmsg)msg
{
const char* messageCString = asl_get( msg, ASL_KEY_MSG );
const char* secondsCString = asl_get( msg, ASL_KEY_TIME );
const char* nanoCString = asl_get( msg, ASL_KEY_TIME_NSEC );
if ( messageCString == NULL || secondsCString == NULL || nanoCString == NULL )
return;
int level = [@(asl_get(msg, ASL_KEY_LEVEL)) intValue];
NSString *levelS =
level == ASL_LEVEL_EMERG ? @"Emergency" :
level == ASL_LEVEL_CRIT ? @"Critical" :
level == ASL_LEVEL_ERR ? @"Error" :
level == ASL_LEVEL_WARNING ? @"Warning" :
level == ASL_LEVEL_NOTICE ? @"Notice" :
level == ASL_LEVEL_INFO ? @"Info" :
level == ASL_LEVEL_DEBUG ? @"Debug" :
@"Unknown";
NSString *sender = [NSString stringWithCString:asl_get(msg, ASL_KEY_SENDER) encoding:NSUTF8StringEncoding];
NSString *message = @(messageCString);
NSString *secondsStr = @(secondsCString);
NSString *nanoStr = @(nanoCString);
NSTimeInterval seconds = [secondsStr doubleValue];
NSTimeInterval nanoSeconds = [nanoStr doubleValue];
NSTimeInterval totalSeconds = seconds + (nanoSeconds / 1e9);
NSDate *timeStamp = [NSDate dateWithTimeIntervalSince1970:totalSeconds];
dispatch_async(dispatch_get_main_queue(), ^{
[self.receiver streamNamed:@"ASL" interceptedLine:message logLevel:levelS at:timeStamp source:sender];
});
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment