BuySellAds.com

My book Barcodes with iOS 7 is nearing completion. Buy it now to get early access!
Our DNA is written in Objective-C
Jump

Accessing the iOS System Log

Peter Reinhardt asks:

The app AppSwitch displays the console entries from NSLog logging in the iphone app. I tried to figure out how they do it but couldnt find an API. Do you have an idea?

Intriguing question! My first gut reaction was that the guys from AppSwitch must have some magic sauce as I didn’t know of a way to access the console log on device like the Xcode organizer is able to. My first response was that probably they are doing some stderr bending as is possible with c++. But then I bought the app to see their trick with my own eyes.

In this blog post I’ll show you how that’s done.

Indeed, when I first launched the app there were several console messages from other apps, so they must have found a method to access these.

I briefly looked at the contents of the log file directories, but /private/var/logs is not readable on device. Plain file reading is out of the question.

The answer to the riddle is ASL, the Apple System Log facility. This is a low-level C API which is present on OSX as well as iOS and as such it has a man page. It turns out you can query the log for messages related to specific apps or just log the entire thing.

A bit of experimentation and dipping into long past C-programming enabled me to come up with this code which takes all current log messages and converts them into a dictionary.

aslmsg q, m;
int i;
const char *key, *val;
 
q = asl_new(ASL_TYPE_QUERY);
 
aslresponse r = asl_search(NULL, q);
while (NULL != (m = aslresponse_next(r)))
{
	NSMutableDictionary *tmpDict = [NSMutableDictionary dictionary];
 
	for (i = 0; (NULL != (key = asl_key(m, i))); i++)
	{
		NSString *keyString = [NSString stringWithUTF8String:(char *)key];
 
		val = asl_get(m, key);
 
		NSString *string = val?[NSString stringWithUTF8String:val]:@"";
		[tmpDict setObject:string forKey:keyString];
	}
 
	NSLog(@"%@", tmpDict);
}
aslresponse_free(r);

The necessary header asl.h can be included without having to add any extra framework. There are some interesting parts to be gleaned from the header. Did you – for example – know that there are more than 3 logging levels?

  • Level 0 – “Emergency”
  • Level 1 – “Alert”
  • Level 2 – “Critical”
  • Level 3 – “Error”
  • Level 4 – “Warning”
  • Level 5 – “Notice”
  • Level 6 – “Info”
  • Level 7 – “Debug”

Since we are actually performing a search there are some nifty options to reduce the number of messages we are getting back. If I only want the messages of the app “Logger”, then I just add the following line after the asl_new:

asl_set_query(q, ASL_KEY_SENDER, "Logger", ASL_QUERY_OP_EQUAL);

To visualize, this is how an NSLog will look like

You can see that there is a unix timestamp, Sender “Logger” is the name of my app and NSLog logs with level 4.

Conclusion

If you know how getting log messages is quite easy for somebody with a bit of C under his belt. For everybody else somebody should write an Objective-C wrapper.

With the above knowledge several interesting usage scenarios suddenly become possible. For example one might want to add a mechanism to your apps to have users in need of support mail you the app logs. Or an framework like the Hockey ad-hoc distribution system might be able to provide access to log files similar to the crash reports you now get on iTunes Connect.

In this article I only covered reading logs. However ASL also offers methods to LOG messages. So I can imagine somebody creating a replacement for NSLog with the ability of customizing your log messages. For example to set lower log levels for debug messages or to even add your own custom keys.

Since AppSwitch is an approved app on the app store we can assume for the time being that using ASL to read the system log is deemed legal.


Categories: Q&A

%d bloggers like this: