diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerStartLogging.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerStartLogging.swift index d073ee41cd1c954b41395d2c0de4760d94ed4b5a..dd4d12b095f3a1df1ed1fe3b52f10b15e9c1d352 100644 --- a/Sources/XXMessengerClient/Messenger/Functions/MessengerStartLogging.swift +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerStartLogging.swift @@ -15,8 +15,7 @@ extension MessengerStartLogging { public static func live(_ env: MessengerEnvironment) -> MessengerStartLogging { return MessengerStartLogging { env.registerLogWriter(.init { messageString in - let message = LogMessage.parse(messageString) - env.log(message) + env.logger(.parse(messageString)) }) } } diff --git a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift index a98e76f042b5e53a6e8556d3bee32d7ebb946162..f37764da5aa19b611aec5322dafa5634ec8d05e3 100644 --- a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift +++ b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift @@ -1,5 +1,4 @@ import Foundation -import Logging import XXClient import XCTestDynamicOverlay @@ -19,7 +18,7 @@ public struct MessengerEnvironment { public var isListeningForMessages: Stored<Bool> public var isRegisteredWithUD: IsRegisteredWithUD public var loadCMix: LoadCMix - public var log: (LogMessage) -> Void + public var logger: MessengerLogger public var login: Login public var lookupUD: LookupUD public var messageListeners: ListenersRegistry @@ -51,9 +50,7 @@ extension MessengerEnvironment { .path public static func live() -> MessengerEnvironment { - let logger = Logger(label: "xx.network.client") - - return MessengerEnvironment( + MessengerEnvironment( authCallbacks: .live(), backup: .inMemory(), backupCallbacks: .live(), @@ -69,7 +66,7 @@ extension MessengerEnvironment { isListeningForMessages: .inMemory(false), isRegisteredWithUD: .live, loadCMix: .live, - log: { logger.log(level: $0.level, .init(stringLiteral: $0.text)) }, + logger: .live(), login: .live, lookupUD: .live, messageListeners: .live(), @@ -112,7 +109,7 @@ extension MessengerEnvironment { isListeningForMessages: .unimplemented(placeholder: false), isRegisteredWithUD: .unimplemented, loadCMix: .unimplemented, - log: XCTUnimplemented("\(Self.self).log"), + logger: .unimplemented, login: .unimplemented, lookupUD: .unimplemented, messageListeners: .unimplemented, diff --git a/Sources/XXMessengerClient/Utils/MessengerLogger.swift b/Sources/XXMessengerClient/Utils/MessengerLogger.swift new file mode 100644 index 0000000000000000000000000000000000000000..0dcf0bc52ca3bdb1c20e935caeefcef9a81b8d8b --- /dev/null +++ b/Sources/XXMessengerClient/Utils/MessengerLogger.swift @@ -0,0 +1,90 @@ +import Foundation +import Logging +import XCTestDynamicOverlay + +public struct MessengerLogger { + public struct Log: Equatable { + public init(level: Logger.Level, message: String) { + self.level = level + self.message = message + } + + public var level: Logger.Level + public var message: String + } + + public var run: (Log, String, String, UInt) -> Void + + public func callAsFunction( + _ item: Log, + file: String = #fileID, + function: String = #function, + line: UInt = #line + ) { + run(item, file, function, line) + } +} + +extension MessengerLogger { + public static func live( + logger: Logger = Logger(label: "xx.network.MessengerClient") + ) -> MessengerLogger { + MessengerLogger { item, file, function, line in + logger.log( + level: item.level, + .init(stringLiteral: item.message), + file: file, + function: function, + line: line + ) + } + } +} + +extension MessengerLogger { + public static let unimplemented = MessengerLogger( + run: XCTUnimplemented("\(Self.self)") + ) +} + +extension MessengerLogger.Log { + static func parse(_ string: String) -> MessengerLogger.Log { + let level: Logger.Level + let message: String + let pattern = #"^([A-Z]+)( \d{4}/\d{2}/\d{2})?( \d{1,2}:\d{2}:\d{2}\.\d+)? (.*)"# + let regex = try! NSRegularExpression( + pattern: pattern, + options: .dotMatchesLineSeparators + ) + let stringRange = NSRange(location: 0, length: string.utf16.count) + if let match = regex.firstMatch(in: string, range: stringRange) { + var groups: [Int: String] = [:] + for rangeIndex in 1..<match.numberOfRanges { + let nsRange = match.range(at: rangeIndex) + if !NSEqualRanges(nsRange, NSMakeRange(NSNotFound, 0)) { + let group = (string as NSString).substring(with: nsRange) + groups[rangeIndex] = group + } + } + level = MessengerLogger.Log.level(form: groups[1]) + message = groups[4] ?? string + } else { + level = .notice + message = string + } + return MessengerLogger.Log(level: level, message: message) + } + + static func level(form string: String?) -> Logger.Level { + switch string { + case "TRACE": return .trace + case "DEBUG": return .debug + case "INFO": return .info + case "WARN": return .warning + case "ERROR": return .error + case "CRITICAL": return .critical + case "FATAL": return .critical + default: return .notice + } + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerStartLoggingTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerStartLoggingTests.swift index b0d0a7c35453348c2f56b4e5e13c973c6fbc639a..d3b4fb38c9e21fea85a58e49c9e6e93f80e5a33f 100644 --- a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerStartLoggingTests.swift +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerStartLoggingTests.swift @@ -6,14 +6,14 @@ import XXClient final class MessengerStartLoggingTests: XCTestCase { func testStartLogging() { var registeredLogWriters: [LogWriter] = [] - var logMessages: [LogMessage] = [] + var logs: [MessengerLogger.Log] = [] var env: MessengerEnvironment = .unimplemented env.registerLogWriter.run = { writer in registeredLogWriters.append(writer) } - env.log = { message in - logMessages.append(message) + env.logger.run = { log, _, _, _ in + logs.append(log) } let start: MessengerStartLogging = .live(env) @@ -23,8 +23,8 @@ final class MessengerStartLoggingTests: XCTestCase { registeredLogWriters.first?.handle("DEBUG Hello, World!") - XCTAssertNoDifference(logMessages, [ - .init(level: .debug, text: "Hello, World!"), + XCTAssertNoDifference(logs, [ + .init(level: .debug, message: "Hello, World!"), ]) } } diff --git a/Tests/XXMessengerClientTests/Utils/MessengerLoggerTests.swift b/Tests/XXMessengerClientTests/Utils/MessengerLoggerTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..755863d99a7d26a35496256bb9be11b776952add --- /dev/null +++ b/Tests/XXMessengerClientTests/Utils/MessengerLoggerTests.swift @@ -0,0 +1,71 @@ +import CustomDump +import XCTest +@testable import XXMessengerClient + +final class MessengerLoggerTests: XCTestCase { + func testParsingLog() { + XCTAssertNoDifference( + MessengerLogger.Log.parse("TRACE Tracing..."), + MessengerLogger.Log(level: .trace, message: "Tracing...") + ) + XCTAssertNoDifference( + MessengerLogger.Log.parse("DEBUG Debugging..."), + MessengerLogger.Log(level: .debug, message: "Debugging...") + ) + XCTAssertNoDifference( + MessengerLogger.Log.parse("INFO Informing..."), + MessengerLogger.Log(level: .info, message: "Informing...") + ) + XCTAssertNoDifference( + MessengerLogger.Log.parse("WARN Warning!"), + MessengerLogger.Log(level: .warning, message: "Warning!") + ) + XCTAssertNoDifference( + MessengerLogger.Log.parse("ERROR Failure!"), + MessengerLogger.Log(level: .error, message: "Failure!") + ) + XCTAssertNoDifference( + MessengerLogger.Log.parse("CRITICAL Critical failure!"), + MessengerLogger.Log(level: .critical, message: "Critical failure!") + ) + XCTAssertNoDifference( + MessengerLogger.Log.parse("FATAL Fatal failure!"), + MessengerLogger.Log(level: .critical, message: "Fatal failure!") + ) + } + + func testParsingFallbacks() { + XCTAssertNoDifference( + MessengerLogger.Log.parse("1234 Wrongly formatted"), + MessengerLogger.Log(level: .notice, message: "1234 Wrongly formatted") + ) + } + + func testParsingStripsDateTime() { + XCTAssertNoDifference( + MessengerLogger.Log.parse("INFO 2022/10/04 Informing..."), + MessengerLogger.Log(level: .info, message: "Informing...") + ) + XCTAssertNoDifference( + MessengerLogger.Log.parse("INFO 23:36:55.755390 Informing..."), + MessengerLogger.Log(level: .info, message: "Informing...") + ) + XCTAssertNoDifference( + MessengerLogger.Log.parse("INFO 2022/10/04 23:36:55.755390 Informing..."), + MessengerLogger.Log(level: .info, message: "Informing...") + ) + } + + func testParsingMultilineMessage() { + XCTAssertNoDifference( + MessengerLogger.Log.parse(""" + ERROR 2022/10/04 23:51:15.021658 First line + Second line + """), + MessengerLogger.Log(level: .error, message: """ + First line + Second line + """) + ) + } +}