77 lines · 2.4 KB · Swift
RawDownload
#if canImport(os)import Foundationimport Loggingimport os struct OSLogLogHandler: LogHandler {    var metadata: Logging.Logger.Metadata = [:]    var logLevel: Logging.Logger.Level = .info     private let label: String    private let subsystem: String    private let logger: os.Logger     init(label: String, subsystem: String) {        self.label = label        self.subsystem = subsystem        let category = Self.category(from: label, subsystem: subsystem)        self.logger = os.Logger(subsystem: subsystem, category: category)    }     subscript(metadataKey metadataKey: String) -> Logging.Logger.Metadata.Value? {        get { self.metadata[metadataKey] }        set { self.metadata[metadataKey] = newValue }    }     func log(event: LogEvent) {        let msg = Self.decorate(            message: event.message.description,            label: self.label,            subsystem: self.subsystem,            metadata: self.metadata,            extraMetadata: event.metadata)         switch event.level {        case .trace:            self.logger.debug("\(msg, privacy: .public)")        case .debug:            self.logger.debug("\(msg, privacy: .public)")        case .info, .notice:            self.logger.info("\(msg, privacy: .public)")        case .warning:            self.logger.warning("\(msg, privacy: .public)")        case .error:            self.logger.error("\(msg, privacy: .public)")        case .critical:            self.logger.fault("\(msg, privacy: .public)")        }    }     private static func category(from label: String, subsystem: String) -> String {        let prefix = subsystem + "."        guard label.hasPrefix(prefix) else { return label }        return String(label.dropFirst(prefix.count))    }     private static func decorate(        message: String,        label: String,        subsystem: String,        metadata: Logging.Logger.Metadata,        extraMetadata: Logging.Logger.Metadata?)        -> String    {        var merged = metadata        if let extraMetadata { merged.merge(extraMetadata, uniquingKeysWith: { _, new in new }) }        guard !merged.isEmpty else { return message }         let suffix = merged            .sorted(by: { $0.key < $1.key })            .map { "\($0.key)=\($0.value)" }            .joined(separator: " ")        _ = label        _ = subsystem        return "\(message) (\(suffix))"    }}#endif