read

OSLog is a unified logging framework available for a long time, but I haven’t adopted it much. But things are about to change with a new feature from WWDC 2023.

Xcode 15 (currently beta) supports structured logging in the debug console.

The problem with logging now

Currently, my Xcode 14 debug console is filled with way too many logs, coming from other frameworks, and even the OS!

2023-07-25 14:39:38.819584+0800 MyApp[12:34] [WC] WCSession is not paired
2023-07-25 14:39:38.819834+0800 MyApp[12:34] [WC] -[WCSession onqueue_handleUpdateSessionState:]_block_invoke dropping as pairingIDs no longer match. pairingID (null), client pairingID: (null)
2023-07-25 14:39:38.997445+0800 MyApp[34:56] [MediaRemote] [ConcreteOutputContext] WARNING: AVF context unavailable for +[MRAVConcreteOutputContext sharedAudioPresentationContext]_block_invoke
2023-07-25 14:39:49.499876+0800 MyApp[56:78] 9.6.0 - [FirebaseAnalytics][I-ACS023007] Analytics v.9.6.0 started
2023-07-25 14:39:49.889278+0800 MyApp[56:78] 9.6.0 - [FirebaseAnalytics][I-ACS023008] To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled (see http://goo.gl/RfcP7r)

There’s too much noise.

I have explored ways on how to reduce debugging logs, but that’s just 1 step too many.

The solution with new Xcode 15

Xcode 15 has added filters, so that I can simply see those from my app (filter subsystem). It even highlights warnings in yellow and errors in red.

Of course, you can also filter with category or messages.

I also prefer to configure the view to not show other metadata, so that each log is just a 1-liner.

Then when you like to see more info, you can press space on the line.

You can even Jump To Source with CMD + OPT + SHIFT + J.

Nice!

Only works for iOS 17

Even if you’re running with Xcode 15, note that structured logging will only work for iOS 17 (beta). Running on iOS 16 will display the logs just like using print. However, you can still open Console app to see it’s glory.

Also, Logger class was introduced in iOS 14. If you supporting any earlier, you can still use the old os_log.

How to log

I often setup all my loggers in an extension. Conventionally, subsystem is your app identifier while category is your module name.

import OSLog
extension Logger {
    private static let appIdentifier = Bundle.main.bundleIdentifier ?? ""
    static let main = Logger(subsystem: appIdentifier, category: "main")
    static let camera = Logger(subsystem: appIdentifier, category: "camera")
}

To use, you can simply Logger.camera.info(...).

For more details on the log levels, you can refer to another of my OSLog post.


Image

@samwize

¯\_(ツ)_/¯

Back to Home