Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xcode 12 and OSLog (os.log): wrapping OSLogMessage causes compile error: Argument must be a string interpolation

In Xcode 12 / iOS 14, OSLog gained support for string interpolation (yay!). But it's still not possible to attach hooks to easily log to other channels, such as Crashlytics.

So I figured I'll just make a simple wrapper and pass on the parameters. However, there seems to be some magic happening regarding string interpolation.

The new Logger class provided, it takes a OSLogMessage as parameter and can be used as follows:

let someVar = "some var"
let logger = Logger(subsystem: "com.my.app", category: "UI")

logger.error("some message")
logger.error("some message with default var: \(someVar)")
logger.error("some message with private var: \(someVar, privacy: .private)")
logger.error("some message with private var: \(someVar, privacy: .private(mask: .hash))")
logger.error("some message with public var: \(someVar, privacy: .public)")

Wrapping the new Logger struct

So lets just wrap this in a struct:

struct MyLogger {
    let logger = Logger(subsystem: "com.my.app", category: "UI")

    func error(_ message: OSLogMessage) {
        logger.error(message)
    }
}

Same signature, but unfortunately, the compiler won't allow this:

ERROR: Argument must be a string interpolation

Furthermore, trying to call my struct also causes a weirdly specific compiler error:

let logger = MyLogger()
let value = "value"
logger.error("Some log message \(value, privacy: .public)")

Yields:

String interpolation cannot be used in this context; if you are calling an os_log function, try a different overload

Directly calling os_log(_: OSLogMessage) instead of the new struct gives the same result.

Is there a way to work around this? Am I missing something?

like image 875
Kevin R Avatar asked Jul 01 '20 11:07

Kevin R


1 Answers

The logging APIs use special compiler features to evaluate the privacy level at compile time. As the diagnostic says, you must use a static (i.e., known at compile time) method or property of ‘OSLogPrivacy’; it can’t be a variable that’s evaluated at run time. The implication is that you can’t create your own wrapper for these APIs without using compiler-internal features.

Apple Forums

like image 121
Shady Mostafa Avatar answered Sep 20 '22 11:09

Shady Mostafa