From cedcad6817994c41c14294709eb6377a50eac13a Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Wed, 5 Oct 2022 00:13:42 +0200
Subject: [PATCH 01/10] Add SwiftLog to example app

---
 Examples/xx-messenger/Package.swift                | 6 ++++++
 Examples/xx-messenger/Sources/AppFeature/App.swift | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/Examples/xx-messenger/Package.swift b/Examples/xx-messenger/Package.swift
index 8e7e2984..accd9923 100644
--- a/Examples/xx-messenger/Package.swift
+++ b/Examples/xx-messenger/Package.swift
@@ -56,6 +56,10 @@ let package = Package(
       url: "https://github.com/pointfreeco/swift-custom-dump.git",
       .upToNextMajor(from: "0.5.2")
     ),
+    .package(
+      url: "https://github.com/apple/swift-log.git",
+      .upToNextMajor(from: "1.4.4")
+    ),
     .package(
       url: "https://github.com/kean/Pulse.git",
       .upToNextMajor(from: "2.1.2")
@@ -104,6 +108,8 @@ let package = Package(
         .target(name: "WelcomeFeature"),
         .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
         .product(name: "ComposablePresentation", package: "swift-composable-presentation"),
+        .product(name: "Logging", package: "swift-log"),
+        .product(name: "PulseLogHandler", package: "Pulse"),
         .product(name: "PulseUI", package: "Pulse"),
         .product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
         .product(name: "XXModels", package: "client-ios-db"),
diff --git a/Examples/xx-messenger/Sources/AppFeature/App.swift b/Examples/xx-messenger/Sources/AppFeature/App.swift
index d6b0b722..7c3f0e82 100644
--- a/Examples/xx-messenger/Sources/AppFeature/App.swift
+++ b/Examples/xx-messenger/Sources/AppFeature/App.swift
@@ -1,8 +1,14 @@
 import ComposableArchitecture
+import Logging
+import PulseLogHandler
 import SwiftUI
 
 @main
 struct App: SwiftUI.App {
+  init() {
+    LoggingSystem.bootstrap(PersistentLogHandler.init)
+  }
+
   var body: some Scene {
     WindowGroup {
       AppView(store: Store(
-- 
GitLab


From e436b0ddf1493fbba6286d2dc98c814b43712d53 Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Wed, 5 Oct 2022 00:20:01 +0200
Subject: [PATCH 02/10] Use SwiftLog in AppCore.Logger

---
 Examples/xx-messenger/Package.swift                  |  2 +-
 .../xx-messenger/Sources/AppCore/Logger/Logger.swift | 12 +++++-------
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/Examples/xx-messenger/Package.swift b/Examples/xx-messenger/Package.swift
index accd9923..30d0173a 100644
--- a/Examples/xx-messenger/Package.swift
+++ b/Examples/xx-messenger/Package.swift
@@ -69,7 +69,7 @@ let package = Package(
     .target(
       name: "AppCore",
       dependencies: [
-        .product(name: "Pulse", package: "Pulse"),
+        .product(name: "Logging", package: "swift-log"),
         .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"),
         .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
         .product(name: "XXDatabase", package: "client-ios-db"),
diff --git a/Examples/xx-messenger/Sources/AppCore/Logger/Logger.swift b/Examples/xx-messenger/Sources/AppCore/Logger/Logger.swift
index 6766d98d..128d3112 100644
--- a/Examples/xx-messenger/Sources/AppCore/Logger/Logger.swift
+++ b/Examples/xx-messenger/Sources/AppCore/Logger/Logger.swift
@@ -1,5 +1,5 @@
 import Foundation
-import Pulse
+import Logging
 import XCTestDynamicOverlay
 
 public struct Logger {
@@ -21,14 +21,12 @@ public struct Logger {
 
 extension Logger {
   public static func live() -> Logger {
-    Logger { msg, file, function, line in
+    let logger = Logging.Logger(label: "xx.network.XXMessengerExample")
+    return Logger { msg, file, function, line in
       switch msg {
       case .error(let error):
-        LoggerStore.shared.storeMessage(
-          label: "xx-messenger",
-          level: .error,
-          message: error.localizedDescription,
-          metadata: [:],
+        logger.error(
+          .init(stringLiteral: error.localizedDescription),
           file: file,
           function: function,
           line: line
-- 
GitLab


From d54a03dc8af06f313b879d56228982c30fad79f0 Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Wed, 5 Oct 2022 01:13:42 +0200
Subject: [PATCH 03/10] Add swift-log dependency

---
 Package.resolved | 9 +++++++++
 Package.swift    | 5 +++++
 2 files changed, 14 insertions(+)

diff --git a/Package.resolved b/Package.resolved
index 225eb0fd..0e663ab0 100644
--- a/Package.resolved
+++ b/Package.resolved
@@ -18,6 +18,15 @@
         "version" : "0.5.2"
       }
     },
+    {
+      "identity" : "swift-log",
+      "kind" : "remoteSourceControl",
+      "location" : "https://github.com/apple/swift-log.git",
+      "state" : {
+        "revision" : "6fe203dc33195667ce1759bf0182975e4653ba1c",
+        "version" : "1.4.4"
+      }
+    },
     {
       "identity" : "xctest-dynamic-overlay",
       "kind" : "remoteSourceControl",
diff --git a/Package.swift b/Package.swift
index 91369715..cd25ca17 100644
--- a/Package.swift
+++ b/Package.swift
@@ -31,6 +31,10 @@ let package = Package(
       url: "https://github.com/kishikawakatsumi/KeychainAccess.git",
       .upToNextMajor(from: "4.2.2")
     ),
+    .package(
+      url: "https://github.com/apple/swift-log.git",
+      .upToNextMajor(from: "1.4.4")
+    ),
   ],
   targets: [
     .target(
@@ -55,6 +59,7 @@ let package = Package(
       dependencies: [
         .target(name: "XXClient"),
         .product(name: "KeychainAccess", package: "KeychainAccess"),
+        .product(name: "Logging", package: "swift-log"),
         .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"),
       ],
       swiftSettings: swiftSettings
-- 
GitLab


From 9d7038f919bb5d2490143229b6688d01ef92ea08 Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Wed, 5 Oct 2022 01:13:49 +0200
Subject: [PATCH 04/10] Add LogMessage model

---
 .../XXMessengerClient/Utils/LogMessage.swift  | 48 +++++++++++++++++++
 .../Utils/LogMessageTests.swift               | 43 +++++++++++++++++
 2 files changed, 91 insertions(+)
 create mode 100644 Sources/XXMessengerClient/Utils/LogMessage.swift
 create mode 100644 Tests/XXMessengerClientTests/Utils/LogMessageTests.swift

diff --git a/Sources/XXMessengerClient/Utils/LogMessage.swift b/Sources/XXMessengerClient/Utils/LogMessage.swift
new file mode 100644
index 00000000..5a213359
--- /dev/null
+++ b/Sources/XXMessengerClient/Utils/LogMessage.swift
@@ -0,0 +1,48 @@
+import Foundation
+import Logging
+
+struct LogMessage: Equatable {
+  var level: Logger.Level
+  var text: String
+}
+
+extension LogMessage {
+  static func parse(_ string: String) -> LogMessage? {
+    let level: Logger.Level
+    let text: String
+    let pattern = #"([A-Z]+) (.*)"#
+    let regex = try! NSRegularExpression(pattern: pattern)
+    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 = .fromString(groups[1])
+      text = groups[2] ?? string
+    } else {
+      level = .notice
+      text = string
+    }
+    return LogMessage(level: level, text: text)
+  }
+}
+
+private extension Logger.Level {
+  static func fromString(_ 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/Utils/LogMessageTests.swift b/Tests/XXMessengerClientTests/Utils/LogMessageTests.swift
new file mode 100644
index 00000000..c955e303
--- /dev/null
+++ b/Tests/XXMessengerClientTests/Utils/LogMessageTests.swift
@@ -0,0 +1,43 @@
+import CustomDump
+import XCTest
+@testable import XXMessengerClient
+
+final class LogMessageTests: XCTestCase {
+  func testParsing() {
+    XCTAssertNoDifference(
+      LogMessage.parse("TRACE Tracing..."),
+      LogMessage(level: .trace, text: "Tracing...")
+    )
+    XCTAssertNoDifference(
+      LogMessage.parse("DEBUG Debugging..."),
+      LogMessage(level: .debug, text: "Debugging...")
+    )
+    XCTAssertNoDifference(
+      LogMessage.parse("INFO Informing..."),
+      LogMessage(level: .info, text: "Informing...")
+    )
+    XCTAssertNoDifference(
+      LogMessage.parse("WARN Warning!"),
+      LogMessage(level: .warning, text: "Warning!")
+    )
+    XCTAssertNoDifference(
+      LogMessage.parse("ERROR Failure!"),
+      LogMessage(level: .error, text: "Failure!")
+    )
+    XCTAssertNoDifference(
+      LogMessage.parse("CRITICAL Critical failure!"),
+      LogMessage(level: .critical, text: "Critical failure!")
+    )
+    XCTAssertNoDifference(
+      LogMessage.parse("FATAL Fatal failure!"),
+      LogMessage(level: .critical, text: "Fatal failure!")
+    )
+  }
+
+  func testParsingFallbacks() {
+    XCTAssertNoDifference(
+      LogMessage.parse("1234 Wrongly formatted"),
+      LogMessage(level: .notice, text: "1234 Wrongly formatted")
+    )
+  }
+}
-- 
GitLab


From b9020a4fd7be0d399326d4af109d568ee7e3669e Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Wed, 5 Oct 2022 01:20:17 +0200
Subject: [PATCH 05/10] Add MessengerSetLogLevel function wrapper

---
 .../Functions/MessengerSetLogLevel.swift      | 22 ++++++++++
 .../Messenger/Messenger.swift                 |  7 ++-
 .../Messenger/MessengerEnvironment.swift      |  3 ++
 .../Functions/MessengerSetLogLevelTests.swift | 44 +++++++++++++++++++
 4 files changed, 74 insertions(+), 2 deletions(-)
 create mode 100644 Sources/XXMessengerClient/Messenger/Functions/MessengerSetLogLevel.swift
 create mode 100644 Tests/XXMessengerClientTests/Messenger/Functions/MessengerSetLogLevelTests.swift

diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerSetLogLevel.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerSetLogLevel.swift
new file mode 100644
index 00000000..21e39bd7
--- /dev/null
+++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerSetLogLevel.swift
@@ -0,0 +1,22 @@
+import XCTestDynamicOverlay
+import XXClient
+
+public struct MessengerSetLogLevel {
+  public var run: (LogLevel) throws -> Bool
+
+  public func callAsFunction(_ logLevel: LogLevel) throws -> Bool {
+    try run(logLevel)
+  }
+}
+
+extension MessengerSetLogLevel {
+  public static func live(_ env: MessengerEnvironment) -> MessengerSetLogLevel {
+    MessengerSetLogLevel(run: env.setLogLevel.run)
+  }
+}
+
+extension MessengerSetLogLevel {
+  public static let unimplemented = MessengerSetLogLevel(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/XXMessengerClient/Messenger/Messenger.swift b/Sources/XXMessengerClient/Messenger/Messenger.swift
index 692d81fd..168cd84a 100644
--- a/Sources/XXMessengerClient/Messenger/Messenger.swift
+++ b/Sources/XXMessengerClient/Messenger/Messenger.swift
@@ -38,6 +38,7 @@ public struct Messenger {
   public var resumeBackup: MessengerResumeBackup
   public var backupParams: MessengerBackupParams
   public var stopBackup: MessengerStopBackup
+  public var setLogLevel: MessengerSetLogLevel
 }
 
 extension Messenger {
@@ -79,7 +80,8 @@ extension Messenger {
       startBackup: .live(env),
       resumeBackup: .live(env),
       backupParams: .live(env),
-      stopBackup: .live(env)
+      stopBackup: .live(env),
+      setLogLevel: .live(env)
     )
   }
 }
@@ -122,6 +124,7 @@ extension Messenger {
     startBackup: .unimplemented,
     resumeBackup: .unimplemented,
     backupParams: .unimplemented,
-    stopBackup: .unimplemented
+    stopBackup: .unimplemented,
+    setLogLevel: .unimplemented
   )
 }
diff --git a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift
index f019df16..bb26093a 100644
--- a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift
+++ b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift
@@ -31,6 +31,7 @@ public struct MessengerEnvironment {
   public var registerForNotifications: RegisterForNotifications
   public var resumeBackup: ResumeBackup
   public var searchUD: SearchUD
+  public var setLogLevel: SetLogLevel
   public var sleep: (TimeInterval) -> Void
   public var storageDir: String
   public var ud: Stored<UserDiscovery?>
@@ -76,6 +77,7 @@ extension MessengerEnvironment {
       registerForNotifications: .live,
       resumeBackup: .live,
       searchUD: .live,
+      setLogLevel: .live,
       sleep: { Thread.sleep(forTimeInterval: $0) },
       storageDir: MessengerEnvironment.defaultStorageDir,
       ud: .inMemory(),
@@ -116,6 +118,7 @@ extension MessengerEnvironment {
     registerForNotifications: .unimplemented,
     resumeBackup: .unimplemented,
     searchUD: .unimplemented,
+    setLogLevel: .unimplemented,
     sleep: XCTUnimplemented("\(Self.self).sleep"),
     storageDir: "unimplemented",
     ud: .unimplemented(),
diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerSetLogLevelTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerSetLogLevelTests.swift
new file mode 100644
index 00000000..d6d44d05
--- /dev/null
+++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerSetLogLevelTests.swift
@@ -0,0 +1,44 @@
+import CustomDump
+import XCTest
+import XXClient
+@testable import XXMessengerClient
+
+final class MessengerSetLogLevelTests: XCTestCase {
+  func testSetLogLevel() throws {
+    var didSetLogLevel: [LogLevel] = []
+    var env: MessengerEnvironment = .unimplemented
+    env.setLogLevel.run = { level in
+      didSetLogLevel.append(level)
+      return true
+    }
+    let setLogLevel: MessengerSetLogLevel = .live(env)
+
+    let result = try setLogLevel(.debug)
+
+    XCTAssertNoDifference(didSetLogLevel, [.debug])
+    XCTAssertNoDifference(result, true)
+  }
+
+  func testSetLogLevelReturnsFalse() throws {
+    var env: MessengerEnvironment = .unimplemented
+    env.setLogLevel.run = { _ in return false }
+    let setLogLevel: MessengerSetLogLevel = .live(env)
+
+    let result = try setLogLevel(.debug)
+
+    XCTAssertNoDifference(result, false)
+  }
+
+  func testSetLogLevelFailure() {
+    struct Failure: Error, Equatable {}
+    let failure = Failure()
+
+    var env: MessengerEnvironment = .unimplemented
+    env.setLogLevel.run = { _ in throw failure }
+    let setLogLevel: MessengerSetLogLevel = .live(env)
+
+    XCTAssertThrowsError(try setLogLevel(.debug)) { error in
+      XCTAssertNoDifference(error as NSError, failure as NSError)
+    }
+  }
+}
-- 
GitLab


From db115cdfd25ffcdb29d9454caa9ff12e10c0c352 Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Wed, 5 Oct 2022 01:24:58 +0200
Subject: [PATCH 06/10] Refactor LogMessage model

---
 Sources/XXMessengerClient/Utils/LogMessage.swift | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/Sources/XXMessengerClient/Utils/LogMessage.swift b/Sources/XXMessengerClient/Utils/LogMessage.swift
index 5a213359..387c536a 100644
--- a/Sources/XXMessengerClient/Utils/LogMessage.swift
+++ b/Sources/XXMessengerClient/Utils/LogMessage.swift
@@ -1,13 +1,18 @@
 import Foundation
 import Logging
 
-struct LogMessage: Equatable {
-  var level: Logger.Level
-  var text: String
+public struct LogMessage: Equatable {
+  public init(level: Logger.Level, text: String) {
+    self.level = level
+    self.text = text
+  }
+
+  public var level: Logger.Level
+  public var text: String
 }
 
 extension LogMessage {
-  static func parse(_ string: String) -> LogMessage? {
+  public static func parse(_ string: String) -> LogMessage {
     let level: Logger.Level
     let text: String
     let pattern = #"([A-Z]+) (.*)"#
-- 
GitLab


From a127f3caf9784e3894aa6d37b9533e5ac72cac47 Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Wed, 5 Oct 2022 01:31:13 +0200
Subject: [PATCH 07/10] Add MessengerStartLogging function

---
 .../Functions/MessengerStartLogging.swift     | 29 ++++++++++++++++++
 .../Messenger/Messenger.swift                 |  7 +++--
 .../Messenger/MessengerEnvironment.swift      | 11 ++++++-
 .../MessengerStartLoggingTests.swift          | 30 +++++++++++++++++++
 4 files changed, 74 insertions(+), 3 deletions(-)
 create mode 100644 Sources/XXMessengerClient/Messenger/Functions/MessengerStartLogging.swift
 create mode 100644 Tests/XXMessengerClientTests/Messenger/Functions/MessengerStartLoggingTests.swift

diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerStartLogging.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerStartLogging.swift
new file mode 100644
index 00000000..d073ee41
--- /dev/null
+++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerStartLogging.swift
@@ -0,0 +1,29 @@
+import Foundation
+import Logging
+import XCTestDynamicOverlay
+import XXClient
+
+public struct MessengerStartLogging {
+  public var run: () -> Void
+
+  public func callAsFunction() -> Void {
+    run()
+  }
+}
+
+extension MessengerStartLogging {
+  public static func live(_ env: MessengerEnvironment) -> MessengerStartLogging {
+    return MessengerStartLogging {
+      env.registerLogWriter(.init { messageString in
+        let message = LogMessage.parse(messageString)
+        env.log(message)
+      })
+    }
+  }
+}
+
+extension MessengerStartLogging {
+  public static let unimplemented = MessengerStartLogging(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/XXMessengerClient/Messenger/Messenger.swift b/Sources/XXMessengerClient/Messenger/Messenger.swift
index 168cd84a..22f11030 100644
--- a/Sources/XXMessengerClient/Messenger/Messenger.swift
+++ b/Sources/XXMessengerClient/Messenger/Messenger.swift
@@ -39,6 +39,7 @@ public struct Messenger {
   public var backupParams: MessengerBackupParams
   public var stopBackup: MessengerStopBackup
   public var setLogLevel: MessengerSetLogLevel
+  public var startLogging: MessengerStartLogging
 }
 
 extension Messenger {
@@ -81,7 +82,8 @@ extension Messenger {
       resumeBackup: .live(env),
       backupParams: .live(env),
       stopBackup: .live(env),
-      setLogLevel: .live(env)
+      setLogLevel: .live(env),
+      startLogging: .live(env)
     )
   }
 }
@@ -125,6 +127,7 @@ extension Messenger {
     resumeBackup: .unimplemented,
     backupParams: .unimplemented,
     stopBackup: .unimplemented,
-    setLogLevel: .unimplemented
+    setLogLevel: .unimplemented,
+    startLogging: .unimplemented
   )
 }
diff --git a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift
index bb26093a..a98e76f0 100644
--- a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift
+++ b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift
@@ -1,4 +1,5 @@
 import Foundation
+import Logging
 import XXClient
 import XCTestDynamicOverlay
 
@@ -18,6 +19,7 @@ public struct MessengerEnvironment {
   public var isListeningForMessages: Stored<Bool>
   public var isRegisteredWithUD: IsRegisteredWithUD
   public var loadCMix: LoadCMix
+  public var log: (LogMessage) -> Void
   public var login: Login
   public var lookupUD: LookupUD
   public var messageListeners: ListenersRegistry
@@ -29,6 +31,7 @@ public struct MessengerEnvironment {
   public var newUdManagerFromBackup: NewUdManagerFromBackup
   public var passwordStorage: PasswordStorage
   public var registerForNotifications: RegisterForNotifications
+  public var registerLogWriter: RegisterLogWriter
   public var resumeBackup: ResumeBackup
   public var searchUD: SearchUD
   public var setLogLevel: SetLogLevel
@@ -48,7 +51,9 @@ extension MessengerEnvironment {
     .path
 
   public static func live() -> MessengerEnvironment {
-    MessengerEnvironment(
+    let logger = Logger(label: "xx.network.client")
+
+    return MessengerEnvironment(
       authCallbacks: .live(),
       backup: .inMemory(),
       backupCallbacks: .live(),
@@ -64,6 +69,7 @@ extension MessengerEnvironment {
       isListeningForMessages: .inMemory(false),
       isRegisteredWithUD: .live,
       loadCMix: .live,
+      log: { logger.log(level: $0.level, .init(stringLiteral: $0.text)) },
       login: .live,
       lookupUD: .live,
       messageListeners: .live(),
@@ -75,6 +81,7 @@ extension MessengerEnvironment {
       newUdManagerFromBackup: .live,
       passwordStorage: .keychain,
       registerForNotifications: .live,
+      registerLogWriter: .live,
       resumeBackup: .live,
       searchUD: .live,
       setLogLevel: .live,
@@ -105,6 +112,7 @@ extension MessengerEnvironment {
     isListeningForMessages: .unimplemented(placeholder: false),
     isRegisteredWithUD: .unimplemented,
     loadCMix: .unimplemented,
+    log: XCTUnimplemented("\(Self.self).log"),
     login: .unimplemented,
     lookupUD: .unimplemented,
     messageListeners: .unimplemented,
@@ -116,6 +124,7 @@ extension MessengerEnvironment {
     newUdManagerFromBackup: .unimplemented,
     passwordStorage: .unimplemented,
     registerForNotifications: .unimplemented,
+    registerLogWriter: .unimplemented,
     resumeBackup: .unimplemented,
     searchUD: .unimplemented,
     setLogLevel: .unimplemented,
diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerStartLoggingTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerStartLoggingTests.swift
new file mode 100644
index 00000000..b0d0a7c3
--- /dev/null
+++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerStartLoggingTests.swift
@@ -0,0 +1,30 @@
+import CustomDump
+import XCTest
+import XXClient
+@testable import XXMessengerClient
+
+final class MessengerStartLoggingTests: XCTestCase {
+  func testStartLogging() {
+    var registeredLogWriters: [LogWriter] = []
+    var logMessages: [LogMessage] = []
+
+    var env: MessengerEnvironment = .unimplemented
+    env.registerLogWriter.run = { writer in
+      registeredLogWriters.append(writer)
+    }
+    env.log = { message in
+      logMessages.append(message)
+    }
+    let start: MessengerStartLogging = .live(env)
+
+    start()
+
+    XCTAssertNoDifference(registeredLogWriters.count, 1)
+
+    registeredLogWriters.first?.handle("DEBUG Hello, World!")
+
+    XCTAssertNoDifference(logMessages, [
+      .init(level: .debug, text: "Hello, World!"),
+    ])
+  }
+}
-- 
GitLab


From f862b214ec05a114b6a8a9fa3ae70c24e4f5c100 Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Wed, 5 Oct 2022 01:35:52 +0200
Subject: [PATCH 08/10] Start logging when creating live AppEnvironment

---
 .../Sources/AppFeature/AppEnvironment+Live.swift             | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
index fef073d1..c4ff9b27 100644
--- a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
+++ b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
@@ -34,6 +34,11 @@ extension AppEnvironment {
     let mainQueue = DispatchQueue.main.eraseToAnyScheduler()
     let bgQueue = DispatchQueue.global(qos: .background).eraseToAnyScheduler()
 
+    defer {
+      _ = try! messenger.setLogLevel(.debug)
+      messenger.startLogging()
+    }
+
     let contactEnvironment = ContactEnvironment(
       messenger: messenger,
       db: dbManager.getDB,
-- 
GitLab


From cd7f9c8c4c6f3d58a7ae8b2b882d8184f2d48e56 Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Wed, 5 Oct 2022 01:48:25 +0200
Subject: [PATCH 09/10] Improve LogeMessage parsing

---
 Sources/XXMessengerClient/Utils/LogMessage.swift  |  4 ++--
 .../Utils/LogMessageTests.swift                   | 15 +++++++++++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/Sources/XXMessengerClient/Utils/LogMessage.swift b/Sources/XXMessengerClient/Utils/LogMessage.swift
index 387c536a..7188f9b0 100644
--- a/Sources/XXMessengerClient/Utils/LogMessage.swift
+++ b/Sources/XXMessengerClient/Utils/LogMessage.swift
@@ -15,7 +15,7 @@ extension LogMessage {
   public static func parse(_ string: String) -> LogMessage {
     let level: Logger.Level
     let text: String
-    let pattern = #"([A-Z]+) (.*)"#
+    let pattern = #"^([A-Z]+)( \d{4}/\d{2}/\d{2})?( \d{1,2}:\d{2}:\d{2}\.\d+)? (.*)$"#
     let regex = try! NSRegularExpression(pattern: pattern)
     let stringRange = NSRange(location: 0, length: string.utf16.count)
     if let match = regex.firstMatch(in: string, range: stringRange) {
@@ -28,7 +28,7 @@ extension LogMessage {
         }
       }
       level = .fromString(groups[1])
-      text = groups[2] ?? string
+      text = groups[4] ?? string
     } else {
       level = .notice
       text = string
diff --git a/Tests/XXMessengerClientTests/Utils/LogMessageTests.swift b/Tests/XXMessengerClientTests/Utils/LogMessageTests.swift
index c955e303..ba6dbe28 100644
--- a/Tests/XXMessengerClientTests/Utils/LogMessageTests.swift
+++ b/Tests/XXMessengerClientTests/Utils/LogMessageTests.swift
@@ -40,4 +40,19 @@ final class LogMessageTests: XCTestCase {
       LogMessage(level: .notice, text: "1234 Wrongly formatted")
     )
   }
+
+  func testParsingStripsDateTime() {
+    XCTAssertNoDifference(
+      LogMessage.parse("INFO 2022/10/04 Informing..."),
+      LogMessage(level: .info, text: "Informing...")
+    )
+    XCTAssertNoDifference(
+      LogMessage.parse("INFO 23:36:55.755390 Informing..."),
+      LogMessage(level: .info, text: "Informing...")
+    )
+    XCTAssertNoDifference(
+      LogMessage.parse("INFO 2022/10/04 23:36:55.755390 Informing..."),
+      LogMessage(level: .info, text: "Informing...")
+    )
+  }
 }
-- 
GitLab


From e7bc04ea1d1a9aaadb5ffbd6b907974c6cf5cc9a Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Wed, 5 Oct 2022 01:56:34 +0200
Subject: [PATCH 10/10] Improve LogeMessage parsing

---
 Sources/XXMessengerClient/Utils/LogMessage.swift    |  7 +++++--
 .../Utils/LogMessageTests.swift                     | 13 +++++++++++++
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/Sources/XXMessengerClient/Utils/LogMessage.swift b/Sources/XXMessengerClient/Utils/LogMessage.swift
index 7188f9b0..7169d953 100644
--- a/Sources/XXMessengerClient/Utils/LogMessage.swift
+++ b/Sources/XXMessengerClient/Utils/LogMessage.swift
@@ -15,8 +15,11 @@ extension LogMessage {
   public static func parse(_ string: String) -> LogMessage {
     let level: Logger.Level
     let text: 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)
+    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] = [:]
diff --git a/Tests/XXMessengerClientTests/Utils/LogMessageTests.swift b/Tests/XXMessengerClientTests/Utils/LogMessageTests.swift
index ba6dbe28..bbea8995 100644
--- a/Tests/XXMessengerClientTests/Utils/LogMessageTests.swift
+++ b/Tests/XXMessengerClientTests/Utils/LogMessageTests.swift
@@ -55,4 +55,17 @@ final class LogMessageTests: XCTestCase {
       LogMessage(level: .info, text: "Informing...")
     )
   }
+
+  func testParsingMultilineMessage() {
+    XCTAssertNoDifference(
+      LogMessage.parse("""
+      ERROR 2022/10/04 23:51:15.021658 First line
+      Second line
+      """),
+      LogMessage(level: .error, text: """
+      First line
+      Second line
+      """)
+    )
+  }
 }
-- 
GitLab