Initial implementation
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.build
|
||||
15
Package.resolved
Normal file
15
Package.resolved
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"originHash" : "041d5a9b2664fe8fba9d0ff5826e7f1955cca0b22d288fe2f2383df27258b52a",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "swift-log",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-log",
|
||||
"state" : {
|
||||
"revision" : "bbd81b6725ae874c69e9b8c8804d462356b55523",
|
||||
"version" : "1.10.1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 3
|
||||
}
|
||||
31
Package.swift
Normal file
31
Package.swift
Normal file
@@ -0,0 +1,31 @@
|
||||
// swift-tools-version: 6.0
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "swift-log-oslog",
|
||||
platforms: [.macOS(.v11), .iOS(.v14), .tvOS(.v14), .watchOS(.v6)],
|
||||
products: [
|
||||
.library(
|
||||
name: "LoggingOSLog",
|
||||
targets: ["LoggingOSLog"]
|
||||
)
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/apple/swift-log", from: "1.10.1"),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "LoggingOSLog",
|
||||
dependencies: [.product(name: "Logging", package: "swift-log")],
|
||||
path: "Sources/Logging OSLog"
|
||||
),
|
||||
.testTarget(
|
||||
name: "LoggingOSLogTests",
|
||||
dependencies: [
|
||||
.product(name: "Logging", package: "swift-log"),
|
||||
"LoggingOSLog"
|
||||
],
|
||||
path: "Tests/Logging OSLog Tests",
|
||||
),
|
||||
]
|
||||
)
|
||||
75
Sources/Logging OSLog/Logging OSLog.swift
Normal file
75
Sources/Logging OSLog/Logging OSLog.swift
Normal file
@@ -0,0 +1,75 @@
|
||||
import Foundation
|
||||
import os
|
||||
import Logging
|
||||
|
||||
public struct LoggingOSLog: LogHandler {
|
||||
public var logLevel: Logging.Logger.Level = .info
|
||||
public var metadata: Logging.Logger.Metadata = [:]
|
||||
public var metadataProvider: Logging.Logger.MetadataProvider?
|
||||
private let oslogger: os.Logger
|
||||
|
||||
public init(label: String) {
|
||||
let lastDotPosition = label.lastIndex(of: ".") ?? label.startIndex
|
||||
let frontPart = label.prefix(upTo: lastDotPosition)
|
||||
let backPart = label.suffix(from: lastDotPosition)
|
||||
guard frontPart.count > 0 else {
|
||||
let subsystem = Bundle.main.bundleIdentifier ?? "SwiftLogToOsLog"
|
||||
self.init(subsystem: subsystem, category: label)
|
||||
return
|
||||
}
|
||||
self.init(subsystem: String(frontPart), category: String(backPart))
|
||||
}
|
||||
|
||||
public init(
|
||||
subsystem: String = Bundle.main.bundleIdentifier ?? "SwiftLogToOsLog",
|
||||
category: String,
|
||||
logLevel: Logging.Logger.Level = .debug
|
||||
) {
|
||||
self.oslogger = os.Logger(subsystem: subsystem, category: category)
|
||||
self.logLevel = logLevel
|
||||
}
|
||||
|
||||
public init(oslog: os.Logger, logLevel: Logging.Logger.Level = .debug) {
|
||||
self.oslogger = oslog
|
||||
self.logLevel = logLevel
|
||||
}
|
||||
|
||||
public func log(
|
||||
level: Logging.Logger.Level,
|
||||
message: Logging.Logger.Message,
|
||||
metadata: Logging.Logger.Metadata?,
|
||||
source: String,
|
||||
file: String,
|
||||
function: String,
|
||||
line: UInt
|
||||
) {
|
||||
let metadataCSV = Self.joinMetadata(self.metadata, self.metadataProvider?.get(), metadata)
|
||||
let messageParts = [message.description, metadataCSV]
|
||||
|
||||
let message = messageParts.compactMap { $0 }.joined(separator: " -> ")
|
||||
self.oslogger.log(level: OSLogType.from(loggerLevel: level), "\(message)")
|
||||
}
|
||||
|
||||
public subscript(metadataKey metadataKey: String) -> Logging.Logger.Metadata.Value? {
|
||||
get {
|
||||
return self.metadata[metadataKey]
|
||||
}
|
||||
set {
|
||||
self.metadata[metadataKey] = newValue
|
||||
}
|
||||
}
|
||||
|
||||
private static func joinMetadata(_ metadataList: Logging.Logger.Metadata?...) -> String? {
|
||||
var metadataAggregator: Logging.Logger.Metadata = [:]
|
||||
for metadata in metadataList {
|
||||
guard let metadata = metadata else { continue }
|
||||
metadataAggregator.merge(metadata) { return $1 }
|
||||
}
|
||||
return Self.joinMetadata(metadataAggregator)
|
||||
}
|
||||
|
||||
private static func joinMetadata(_ metadata: Logging.Logger.Metadata, with separator: String = ", ") -> String? {
|
||||
guard !metadata.isEmpty else { return nil }
|
||||
return metadata.map { "\($0) = \($1)" }.joined(separator: separator)
|
||||
}
|
||||
}
|
||||
23
Sources/Logging OSLog/OSLog Extension.swift
Normal file
23
Sources/Logging OSLog/OSLog Extension.swift
Normal file
@@ -0,0 +1,23 @@
|
||||
import Logging
|
||||
import os
|
||||
|
||||
extension OSLogType {
|
||||
static func from(loggerLevel: Logging.Logger.Level) -> Self {
|
||||
switch loggerLevel {
|
||||
case .trace:
|
||||
return .debug
|
||||
case .debug:
|
||||
return .debug
|
||||
case .info:
|
||||
return .info
|
||||
case .notice:
|
||||
return .default
|
||||
case .warning:
|
||||
return .info
|
||||
case .error:
|
||||
return .error
|
||||
case .critical:
|
||||
return .fault
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Tests/Logging OSLog Tests/Logging Test.swift
Normal file
16
Tests/Logging OSLog Tests/Logging Test.swift
Normal file
@@ -0,0 +1,16 @@
|
||||
import Testing
|
||||
import Logging
|
||||
import LoggingOSLog
|
||||
|
||||
@Test func isConstructable() {
|
||||
let _ = LoggingOSLog(subsystem: "de.astzweig.app", category: "Image Processing")
|
||||
}
|
||||
|
||||
@Test func canAddAsLoggingBackend() {
|
||||
LoggingSystem.bootstrap(LoggingOSLog.init)
|
||||
}
|
||||
|
||||
@Test func canLogMessage() {
|
||||
let logger = Logging.Logger(label: "de.astzweig.loggingoslog.Test")
|
||||
logger.info("Test message")
|
||||
}
|
||||
Reference in New Issue
Block a user