diff --git a/Package.swift b/Package.swift index ae60e71b..44e274fb 100644 --- a/Package.swift +++ b/Package.swift @@ -37,7 +37,7 @@ let package = Package( targets: ["CocoaLumberjackSwiftLogBackend"]), ], dependencies: [ - .package(url: "https://github.com/apple/swift-log", from: "1.5.0"), + .package(url: "https://github.com/apple/swift-log", from: "1.11.0"), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift index 0c1a35e5..65064f4e 100644 --- a/Package@swift-6.0.swift +++ b/Package@swift-6.0.swift @@ -31,7 +31,7 @@ let package = Package( targets: ["CocoaLumberjackSwiftLogBackend"]), ], dependencies: [ - .package(url: "https://github.com/apple/swift-log", from: "1.5.0"), + .package(url: "https://github.com/apple/swift-log", from: "1.11.0"), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/Package@swift-6.1.swift b/Package@swift-6.1.swift index 19dfc0a6..1eaceeeb 100644 --- a/Package@swift-6.1.swift +++ b/Package@swift-6.1.swift @@ -32,7 +32,7 @@ let package = Package( targets: ["CocoaLumberjackSwiftLogBackend"]), ], dependencies: [ - .package(url: "https://github.com/apple/swift-log", from: "1.5.0"), + .package(url: "https://github.com/apple/swift-log", from: "1.11.0"), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/Package@swift-6.2.swift b/Package@swift-6.2.swift index 2631a927..1cc49da2 100644 --- a/Package@swift-6.2.swift +++ b/Package@swift-6.2.swift @@ -35,7 +35,7 @@ let package = Package( targets: ["CocoaLumberjackSwiftLogBackend"]), ], dependencies: [ - .package(url: "https://github.com/apple/swift-log", from: "1.5.0"), + .package(url: "https://github.com/apple/swift-log", from: "1.11.0"), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/Sources/CocoaLumberjackSwiftLogBackend/DDLogHandler.swift b/Sources/CocoaLumberjackSwiftLogBackend/DDLogHandler.swift index a1f1c9c6..a09bacfd 100644 --- a/Sources/CocoaLumberjackSwiftLogBackend/DDLogHandler.swift +++ b/Sources/CocoaLumberjackSwiftLogBackend/DDLogHandler.swift @@ -112,6 +112,17 @@ public struct DDLogHandler: LogHandler { } @inlinable + public func log(event: LogEvent) { + let slMessage = SwiftLogMessage(loggerLabel: loggerInfo.label, + loggerMetadata: loggerInfo.metadataSources.logger, + loggerProvidedMetadata: loggerInfo.metadataSources.provider?.get(), + event: event) + config.log.log(asynchronous: _logAsync(level: event.level, metadata: event.metadata), message: slMessage) + } + + // Not removed because it's `@inlinable`. + @inlinable + @available(*, deprecated, renamed: "log(event:)") public func log(level: Logging.Logger.Level, message: Logging.Logger.Message, metadata: Logging.Logger.Metadata?, @@ -119,17 +130,13 @@ public struct DDLogHandler: LogHandler { file: String, function: String, line: UInt) { - let slMessage = SwiftLogMessage(loggerLabel: loggerInfo.label, - loggerMetadata: loggerInfo.metadataSources.logger, - loggerProvidedMetadata: loggerInfo.metadataSources.provider?.get(), - message: message, - level: level, - metadata: metadata, - source: source, - file: file, - function: function, - line: line) - config.log.log(asynchronous: _logAsync(level: level, metadata: metadata), message: slMessage) + log(event: .init(level: level, + message: message, + metadata: metadata, + source: source, + file: file, + function: function, + line: line)) } } diff --git a/Sources/CocoaLumberjackSwiftLogBackend/DDLogMessage+SwiftLogInformation.swift b/Sources/CocoaLumberjackSwiftLogBackend/DDLogMessage+SwiftLogInformation.swift index d65e26ff..8a96f737 100644 --- a/Sources/CocoaLumberjackSwiftLogBackend/DDLogMessage+SwiftLogInformation.swift +++ b/Sources/CocoaLumberjackSwiftLogBackend/DDLogMessage+SwiftLogInformation.swift @@ -18,7 +18,7 @@ public import Logging extension DDLogMessage { /// Contains the swift-log details of a given log message. - public struct SwiftLogInformation: Equatable, Sendable { + public struct SwiftLogInformation: Sendable { /// Contains information about the swift-log logger that logged this message. public struct LoggerInformation: Equatable, Sendable { /// Contains the metadata from the various sources of on a logger. @@ -29,18 +29,19 @@ extension DDLogMessage { /// The metadata of the metadata provider on the swift-log logger that logged this message. public let provider: Logging.Logger.Metadata? } - + /// The label of the swift-log logger that logged this message. public let label: String /// The metadata of the swift-log logger that logged this message. public let metadataSources: MetadataSources - + /// The metadata of the swift-log logger that logged this message. @available(*, deprecated, renamed: "metadataSources.logger") public var metadata: Logging.Logger.Metadata { metadataSources.logger } } - + /// Contains information about the swift-log message thas was logged. + @available(*, deprecated, message: "Use `LogeEvent` from swift-log instead.") public struct MessageInformation: Equatable, Sendable { /// The original swift-log message. public let message: Logging.Logger.Message @@ -51,11 +52,19 @@ extension DDLogMessage { /// The original swift-log source of the message. public let source: String } - + /// The information about the swift-log logger that logged this message. public let logger: LoggerInformation + /// The original event swift-log event. + /// Some of the information contained in this event is also available on the ``DDLogMessage`` itself. + /// Other information (like ``SwiftLogInformation/event/level`` vs ``DDLogMessage/level`` & ``DDLogMessage/flag``) might be more fine-grained. + public let event: Logging.LogEvent + /// The information about the swift-log message that was logged. - public let message: MessageInformation + @available(*, deprecated, renamed: "event") + public var message: MessageInformation { + .init(message: event.message, level: event.level, metadata: event.metadata, source: event.source) + } /// Merges the metadata from all layers together. /// The metadata on the logger provides the base. @@ -68,7 +77,7 @@ extension DDLogMessage { if let providerMetadata = logger.metadataSources.provider { merged.merge(providerMetadata, uniquingKeysWith: { $1 }) } - if let messageMetadata = message.metadata { + if let messageMetadata = event.metadata { merged.merge(messageMetadata, uniquingKeysWith: { $1 }) } return merged @@ -81,3 +90,18 @@ extension DDLogMessage { (self as? SwiftLogMessage)?._swiftLogInfo } } + +@available(*, deprecated, message: "The contained `LogEvent` of swift-log is not Equatable. Thus this implementation is bound to be out of date and possibly inaccurate.") +extension DDLogMessage.SwiftLogInformation: Equatable { + public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.logger == rhs.logger + && lhs.event.message == rhs.event.message + && lhs.event.level == rhs.event.level + && lhs.event.metadata == rhs.event.metadata + && lhs.event.source == rhs.event.source + && lhs.event.file == rhs.event.file + && lhs.event.function == rhs.event.function + && lhs.event.line == rhs.event.line + && (lhs.event.error == nil) == (rhs.event.error == nil) + } +} diff --git a/Sources/CocoaLumberjackSwiftLogBackend/SwiftLogMessage.swift b/Sources/CocoaLumberjackSwiftLogBackend/SwiftLogMessage.swift index 66be6dd5..9956d0a4 100644 --- a/Sources/CocoaLumberjackSwiftLogBackend/SwiftLogMessage.swift +++ b/Sources/CocoaLumberjackSwiftLogBackend/SwiftLogMessage.swift @@ -38,41 +38,62 @@ final class SwiftLogMessage: DDLogMessage, @unchecked Sendable { let _swiftLogInfo: SwiftLogInformation @usableFromInline - init(loggerLabel: String, - loggerMetadata: Logging.Logger.Metadata, - loggerProvidedMetadata: Logging.Logger.Metadata?, - message: Logging.Logger.Message, - level: Logging.Logger.Level, - metadata: Logging.Logger.Metadata?, - source: String, - file: String, - function: String, - line: UInt) { - _swiftLogInfo = .init(logger: .init(label: loggerLabel, - metadataSources: .init(logger: loggerMetadata, - provider: loggerProvidedMetadata)), - message: .init(message: message, - level: level, - metadata: metadata, - source: source)) - let (ddLogLevel, ddLogFlag) = level.ddLogLevelAndFlag - let msg = String(describing: message) + init(loggerInfo: SwiftLogInformation.LoggerInformation, event: LogEvent) { + _swiftLogInfo = .init(logger: loggerInfo, event: event) + let (ddLogLevel, ddLogFlag) = event.level.ddLogLevelAndFlag + let msg = String(describing: event.message) super.init(format: msg, formatted: msg, // We have no chance in retrieving the original format here. level: ddLogLevel, flag: ddLogFlag, context: 0, - file: file, - function: function, - line: line, + file: event.file, + function: event.function, + line: event.line, tag: nil, options: .dontCopyMessage, // Swift will bridge to NSString. No need to make an additional copy. timestamp: nil) // Passing nil will make DDLogMessage create the timestamp which saves us the bridging between Date and NSDate. } + @usableFromInline + convenience init(loggerLabel: String, + loggerMetadata: Logging.Logger.Metadata, + loggerProvidedMetadata: Logging.Logger.Metadata?, + event: LogEvent) { + self.init(loggerInfo: .init(label: loggerLabel, + metadataSources: .init(logger: loggerMetadata, + provider: loggerProvidedMetadata)), + event: event) + } + // Not removed due to `@usableFromInline`. @usableFromInline - @available(*, deprecated, renamed: "init(loggerLabel:loggerMetadata:loggerMetadata:message:level:metadata:source:file:function:line:)") + @available(*, deprecated, renamed: "init(loggerLabel:loggerMetadata:loggerProvidedMetadata:event:)") + convenience init(loggerLabel: String, + loggerMetadata: Logging.Logger.Metadata, + loggerProvidedMetadata: Logging.Logger.Metadata?, + message: Logging.Logger.Message, + level: Logging.Logger.Level, + metadata: Logging.Logger.Metadata?, + source: String, + file: String, + function: String, + line: UInt) { + self.init(loggerLabel: loggerLabel, + loggerMetadata: loggerMetadata, + loggerProvidedMetadata: loggerProvidedMetadata, + event: .init(level: level, + message: message, + metadata: metadata, + source: source, + file: file, + function: function, + line: line)) + } + + // Not removed due to `@usableFromInline`. + @usableFromInline + @available(*, deprecated, renamed: "init(loggerLabel:loggerMetadata:loggerProvidedMetadata:message:level:metadata:source:file:function:line:)") convenience init(loggerLabel: String, loggerMetadata: Logging.Logger.Metadata, message: Logging.Logger.Message, @@ -95,6 +116,17 @@ final class SwiftLogMessage: DDLogMessage, @unchecked Sendable { } override func isEqual(_ object: Any?) -> Bool { - super.isEqual(object) && (object as? SwiftLogMessage)?._swiftLogInfo == _swiftLogInfo + guard super.isEqual(object), let otherSwiftMsg = object as? SwiftLogMessage else { return false } + let otherInfo = otherSwiftMsg._swiftLogInfo + // This is an approximation to fulfill most of the use cases of comparing DDLogMessages... + return otherInfo.logger == _swiftLogInfo.logger + && otherInfo.event.message == _swiftLogInfo.event.message + && otherInfo.event.level == _swiftLogInfo.event.level + && otherInfo.event.metadata == _swiftLogInfo.event.metadata + && otherInfo.event.source == _swiftLogInfo.event.source + && otherInfo.event.file == _swiftLogInfo.event.file + && otherInfo.event.function == _swiftLogInfo.event.function + && otherInfo.event.line == _swiftLogInfo.event.line + && (otherInfo.event.error == nil) == (_swiftLogInfo.event.error == nil) } } diff --git a/Tests/CocoaLumberjackSwiftLogBackendTests/DDLogHandlerTests.swift b/Tests/CocoaLumberjackSwiftLogBackendTests/DDLogHandlerTests.swift index 2a36b196..46d9df86 100644 --- a/Tests/CocoaLumberjackSwiftLogBackendTests/DDLogHandlerTests.swift +++ b/Tests/CocoaLumberjackSwiftLogBackendTests/DDLogHandlerTests.swift @@ -66,13 +66,9 @@ final class DDLogHandlerTests: XCTestCase { XCTAssertEqual(loggedMsg.message.function, #function) XCTAssertEqual(loggedMsg.message.line, logLine) XCTAssertNotNil(loggedMsg.message.swiftLogInfo) - XCTAssertEqual(loggedMsg.message.swiftLogInfo, .init(logger: .init(label: logger.label, - metadataSources: .init(logger: logger.handler.metadata, - provider: logger.metadataProvider?.get())), - message: .init(message: msg, - level: .info, - metadata: nil, - source: logSource))) + XCTAssertEqual(loggedMsg.message.swiftLogInfo?.logger, .init(label: logger.label, + metadataSources: .init(logger: logger.handler.metadata, + provider: logger.metadataProvider?.get()))) } func testBootstrappingWithExplicitMethod() throws { @@ -91,13 +87,9 @@ final class DDLogHandlerTests: XCTestCase { XCTAssertEqual(loggedMsg.message.function, #function) XCTAssertEqual(loggedMsg.message.line, logLine) XCTAssertNotNil(loggedMsg.message.swiftLogInfo) - XCTAssertEqual(loggedMsg.message.swiftLogInfo, .init(logger: .init(label: logger.label, - metadataSources: .init(logger: logger.handler.metadata, - provider: logger.metadataProvider?.get())), - message: .init(message: msg, - level: .info, - metadata: nil, - source: logSource))) + XCTAssertEqual(loggedMsg.message.swiftLogInfo?.logger, .init(label: logger.label, + metadataSources: .init(logger: logger.handler.metadata, + provider: logger.metadataProvider?.get()))) } func testDefaults() throws { @@ -148,13 +140,9 @@ final class DDLogHandlerTests: XCTestCase { XCTAssertEqual(loggedMsg1.message.function, #function) XCTAssertEqual(loggedMsg1.message.line, logLine1) XCTAssertNotNil(loggedMsg1.message.swiftLogInfo) - XCTAssertEqual(loggedMsg1.message.swiftLogInfo, .init(logger: .init(label: logger.label, - metadataSources: .init(logger: logger.handler.metadata, - provider: logger.metadataProvider?.get())), - message: .init(message: "\(level)-msg", - level: level, - metadata: message1Meta, - source: logSource))) + XCTAssertEqual(loggedMsg1.message.swiftLogInfo?.logger, .init(label: logger.label, + metadataSources: .init(logger: logger.handler.metadata, + provider: logger.metadataProvider?.get()))) let loggedMsg2 = mockDDLog.loggedMessages[$0.1 + 1] XCTAssertFalse(loggedMsg2.async) @@ -165,13 +153,9 @@ final class DDLogHandlerTests: XCTestCase { XCTAssertEqual(loggedMsg2.message.function, #function) XCTAssertEqual(loggedMsg2.message.line, logLine2) XCTAssertNotNil(loggedMsg2.message.swiftLogInfo) - XCTAssertEqual(loggedMsg2.message.swiftLogInfo, .init(logger: .init(label: logger.label, - metadataSources: .init(logger: logger.handler.metadata, - provider: logger.metadataProvider?.get())), - message: .init(message: "\(level)-msg-with-sync", - level: level, - metadata: message2Meta, - source: logSource))) + XCTAssertEqual(loggedMsg2.message.swiftLogInfo?.logger, .init(label: logger.label, + metadataSources: .init(logger: logger.handler.metadata, + provider: logger.metadataProvider?.get()))) } } }