Logging to the Mac's console is totally unreliable, especially with release builds

I've noticed issues with logging in the Mac's console app for a very long time now (from Xcode 15?) but have just spent several hours trying to objectively observe and monitor what's going on and try to set up reliable logging. But I've totally been unable to and my conclusion is that logging just absolutely cannot be relied upon at all, its so chronically bad as to be unusable.

If I for example add some logging lines right at the start of didFinishLaunchingWithOptions() and use a variety of logging mechanisms NSLog(), print(),os_log_with_type(), OSLog() (AppDelegate is in Obj-C and calls Obj-C logging, then calls a swift function for Swift logging), then none of them are reliable.

If the app is build/installed via Xcode then logging is reliable within Xcode's console and also within the Mac's console app. But then if the app is uploaded/installed via Testflight it's a very different matter. Sometimes, but not very often, the logging is as expected, but more often than not, some of it is missing. How much is missing seems totally random, sometimes its a little, sometimes its a lot, and something else that very very often happens is there's lots of duplicate logging, each logging line will appear 2 or three times.

Here's a very simple example to illustrate what happens (in this example for simplicity I'm just showing using NSLog, don't focus on that as I know NSLog is "old", its the exact same result regardless of how the logging is actually performed).

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    appDelegate = self;

NSLog(@"Log line 1");
NSLog(@"Log line 2");
NSLog(@"Log line 3");
NSLog(@"Log line 4");
NSLog(@"Log line 5");

When the app is downloaded from Testflight then only very rarely will I see 5 lines of logging, sometimes it'll be 4, sometimes 2, sometimes none. And quite often the logging is duplicated i.e. I might see for example in the Console app:

Log line 1
Log line 1
Log line 2
Log line 2
Log line 3
Log line 3

In general it's just totally unusable and unreliable. It just cannot be be used at all. Why is it this bad? What can be done to make logging reliable and useful? I've spent days and days reading the recommended approaches, trying things out, including the new stuff like OSLog etc. But it remains dreadful. What is the recommended approach to make logging 100% reliable?

There's never any problem with Xcode's console, it's only with the Mac's console app. However, when an app is being tested which has been installed from Testflight then using Xcode's console can't be used. So If a QA team find problems with a Testflight build and attach the Console log its utterly useless as its contents are effectively random.

In general it's just totally unusable and unreliable. It just cannot be be used at all. Why is it this bad? What can be done to make logging reliable and useful? I've spent days and days reading the recommended approaches, trying things out, including the new stuff like OSLog etc. But it remains dreadful. What is the recommended approach to make logging 100% reliable?

How are you monitoring the log data? The big issue here is that the systems logging volume is often higher than what can be physically transported by console.app over the network connection to the device. At that point, it's only option is to "drop" data in order to try and keep up with the "current" stream. The solution to this issue is to not rely on the "live" log, but instead collect a sysdiagnose and use Console to access the log archive. I'd also recommend taking a look at "Your Friend the System Log" for more tips and suggestions on both collection and analysis.

There's never any problem with Xcode's console, it's only with the Mac's console app.

Depending on Xcode version and the logging function, you're either seeing the output of stderr or seeing a highly filtered stream from the "full" log. The post "Your Friend the System Log" has more details on this, but basic answer here is that Xcode is hooked into your apps process and the device in ways that can make it more reliable at monitoring "live" data*.

*Strictly speaking, I think you could actually get Xcode to generate very similar failure patterns, however, I think it would different scenarios than Console.app and (probably) require much higher log volumes from your app.

However, when an app is being tested which has been installed from Testflight then using Xcode's console can't be used. So If a QA team find problems with a Testflight build and attach the Console log its utterly useless as its contents are effectively random.

Expanding on what I said earlier, I think what you're QA team is currently doing is monitoring via Console.app and then saving the output if/when they see/find a problem. On a high volume device that basically means you're getting whatever data "happened" to make it through an overly narrow transmission pipe... which can be pretty useless.

However, the actual log data was still written on the local device, even if it couldn't reach the Mac, and pulling the sysdiagnose data (or extracting the data through the command line) will get you the "full" data you actually want.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Logging to the Mac's console is totally unreliable, especially with release builds
 
 
Q