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
We have one called DeviceStats and indeed we also use ASL for this. It’s very powerful
Those 8 logging levels actually come from ancient Unix history: syslog. Originally created for and used solely by Sendmail in the 1980s, it eventually became the de-facto logging system for all Unix systems. It’s not surprising Apple implemented their logging with identical levels.
First of all why just not to simply use iTunes crash reports.
It’s a nice technical trick, buy I am as a user don’t want to know sys log 🙂
The second thing it reminds me is Xcode and its Instruments. They are more powerful than a lot of people think. Please watch WWDC 2010 “Session 309 – Advanced Performance Analysis with Instruments” and “Session 311 – Advanced Memory Analysis with Instruments”. Must known!
I put together a Cocoa wrapper around ASL for writing log messages called SOLogger. I’ve been using it on iOS for a while now.
On GitHub:
On BitBucket:
Jim Dovey has a wrapper, ASLogger, that also supports querying ASL for messages.
Bill
Found an interesting note for IOS developers. The ASL implementation on the device will limit you to searching only the last 256 messages. Watch out for that one.
In your code sample, should you also be calling asl_free on q?
how about idevice syslog very simple and easy to use.Just enable to the ms logs where ever you want the loggin to be there.
This design is wicked! You most certainly know how to keep a reader entertained.
Between your wit and your videos, I was almost moved to start my own blog (well, almost…HaHa!)
Fantastic job. I really loved what you had to say, and more than that,
how you presented it. Too cool!