Portrait

I2H3

Notes from work as an app developer for iPhones, iPads and Macs.

RSS Icon GitHub Mastodon

Logging Macro

With the introduction of Swift macros in 2023, I have came across a few situations in which they have become useful. One is the reduction of boilerplate code. In example the automatic declaration of a Logger property on a type.

I do not know about you, but to me the optional subsystem and category arguments for a Logger object are helpful in filtering logs. Also, such logger objects should be specific to objects of the type they are used in because in some cases individual states matter. That results in a lot of boilerplate code across a codebase which can be added automatically by a macro now.

In essence, adding the attribute @Logging to a type will add the following declaration automatically:

/// Specific `Logger` for this instance of ``Example``.
private let logger: Logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "", category: "Example")

Note the automatic resolution of the type name which is used as the value for the category argument. That happens automatically during compile by leveraging the power of SwiftSyntax package by Apple.

The actual usage would look like this:

import Logging

@Logging
class Example {
    func sayHello() {
        logger.notice("Hello!")
    }
}

let example = Example()
example.sayHello()

Which will result in such a log message:

Hello!