Sources/OSS/Logging/LogAgent.swift (90 lines of code) (raw):
public protocol LogAgent: Sendable {
/// name of the struct or class where the logger was instantiated from
var name: String { get }
/// Log a message passing the log level as a parameter.
///
/// If the ``LogAgentLevel`` passed to this method is more severe than the `Logger`'s ``logLevel``, it will be logged,
/// otherwise nothing will happen.
///
/// - parameters:
/// - level: The log level to log `message` at. For the available log levels, see `LogAgentLevel`.
/// - message: The message to be logged. `message` can be used with any string interpolation literal.
/// - metadata: One-off metadata to attach to this log message.
/// - source: The source this log messages originates from. Defaults
/// to the module emitting the log message.
/// - file: The file this log message originates from (there's usually no need to pass it explicitly as it
/// defaults to `#fileID`.
/// - function: The function this log message originates from (there's usually no need to pass it explicitly as
/// it defaults to `#function`).
/// - line: The line this log message originates from (there's usually no need to pass it explicitly as it
/// defaults to `#line`).
func log(level: LogAgentLevel,
message: @autoclosure () -> String,
metadata: @autoclosure () -> [String: String]?,
source: @autoclosure () -> String,
file: String,
function: String,
line: UInt)
}
/// Convenience wrapper functions that call `self.log()` with corresponding log level.
public extension LogAgent {
/// Use for messages that are typically seen during trace.
func trace(
_ message: @autoclosure () -> String,
file: String = #fileID,
function: String = #function,
line: UInt = #line
) {
log(level: .trace,
message: message(),
metadata: nil,
source: currentModule(fileID: file),
file: file,
function: function,
line: line)
}
/// Use for messages that are typically seen during debugging.
func debug(
_ message: @autoclosure () -> String,
file: String = #fileID,
function: String = #function,
line: UInt = #line
) {
log(level: .debug,
message: message(),
metadata: nil,
source: currentModule(fileID: file),
file: file,
function: function,
line: line)
}
/// Use for informational messages.
func info(
_ message: @autoclosure () -> String,
file: String = #fileID,
function: String = #function,
line: UInt = #line
) {
log(level: .info,
message: message(),
metadata: nil,
source: currentModule(fileID: file),
file: file,
function: function,
line: line)
}
/// Use for non-error messages that are more severe than `.notice`.
func warn(
_ message: @autoclosure () -> String,
file: String = #fileID,
function: String = #function,
line: UInt = #line
) {
log(level: .warn,
message: message(),
metadata: nil,
source: currentModule(fileID: file),
file: file,
function: function,
line: line)
}
/// Use for errors.
func error(
_ message: @autoclosure () -> String,
file: String = #fileID,
function: String = #function,
line: UInt = #line
) {
log(level: .error,
message: message(),
metadata: nil,
source: currentModule(fileID: file),
file: file,
function: function,
line: line)
}
}
private func currentModule(fileID: String = #fileID) -> String {
let utf8All = fileID.utf8
if let slashIndex = utf8All.firstIndex(of: UInt8(ascii: "/")) {
return String(fileID[..<slashIndex])
} else {
return "n/a"
}
}