Reputation: 2809
I'm working on a company project that requires me to log to a specific server, but I want to log to the console simultaneously. I use a custom logging class that I can feed a log message, a log level, a category and the source location where the log message was generated. Depending on where the app runs, it will log to the console (development), a development backend (test) or the production backend (production).
With Xcode 15 I'm finding the console output of OSLog beautiful and want to use it instead of the print statement. Now I want to also utilize the functionality of OSLog as much as I can and one thing is bothering me: right clicking a log entry in the console and using "Jump to source" always shows the line inside the class where I determine if we log to OSLog or to one of the backends.
Reading through Apple's documentation and looking at the available methods I can't find a way to override the default source location used by OSLog/Xcode to determine the source of a log message. Is there a way to modify it?
Upvotes: 6
Views: 437
Reputation: 307
You may be able to do this by inlining your wrapper around os.Logger
. However, @inlinable
doesn't work in Debug builds and @inline(__always)
when the SWIFT_OPTIMIZATION_LEVEL
is set to -O
doesn't force the compiler to inline the implementation.
A workaround is using @_transparent (note that it's an underscored attribute; so, use it with care). Also, you'll need to put your wrapper in another module; otherwise, the call site will show up as ../<compiler-generated>
since the implementation has become part of the binary interface of the module.
A very simple implementation will look like this:
import os
@frozen
public enum App {
public static let log: Logger = {
Logger()
}()
struct Logger: Sendable {
@_transparent
public func debug(
_ message: String,
fileID: StaticString = #fileID,
filePath: StaticString = #file,
function: StaticString = #function,
line: UInt = #line
) {
let formattedMessage = "Do some stuff... \(message)"
let logger = os.Logger(subsystem: "can use fileID", category: "placeholder")
logger.debug("\(function):#\(line): \(formattedMessage)")
}
}
}
If the implementation of the wrapper changes, the caller needs to be recompiled. The enum is annotated with @frozen
; so, it's promising no changes to its callers.
Upvotes: -1
Reputation: 26351
You can't. Apple implemented OSLog on a compiler/toolchain level, so the option to pass in file and line info is unavailable.
This unfortunately means you'll have to use OSLog directly, not wrapped, in order to get the Xcode integration working.
Upvotes: 2