From 95a4c560f0e3d3b13ec534e6d6ebbef8bd74d04d Mon Sep 17 00:00:00 2001 From: Luiz Rodrigo Martins Barbosa Date: Tue, 8 Dec 2020 18:07:00 +0100 Subject: [PATCH 1/2] Add file logger --- .../LoggerMiddleware/LoggerMiddleware.swift | 161 +++++++++++++----- 1 file changed, 118 insertions(+), 43 deletions(-) diff --git a/Sources/LoggerMiddleware/LoggerMiddleware.swift b/Sources/LoggerMiddleware/LoggerMiddleware.swift index 2e8e843..92b40b5 100644 --- a/Sources/LoggerMiddleware/LoggerMiddleware.swift +++ b/Sources/LoggerMiddleware/LoggerMiddleware.swift @@ -4,22 +4,10 @@ import SwiftRex extension Middleware where StateType: Equatable { public func logger( - actionTransform: @escaping (InputActionType, ActionSource) -> String = { - "\nšŸ•¹ \($0)\nšŸŽŖ \($1.file.split(separator: "/").last ?? ""):\($1.line) \($1.function)" - }, - actionPrinter: @escaping (String) -> Void = { os_log(.debug, log: .default, "%{PUBLIC}@", $0) }, - stateDiffTransform: @escaping (StateType?, StateType) -> String? = { - let stateBefore = dumpToString($0) - let stateAfter = dumpToString($1) - return Difference.diff(old: stateBefore, new: stateAfter, linesOfContext: 2, prefixLines: "šŸ› ") - }, - stateDiffPrinter: @escaping (String?) -> Void = { state in - if let state = state { - os_log(.debug, log: .default, "%{PUBLIC}@", state) - } else { - os_log(.debug, log: .default, "%{PUBLIC}@", "šŸ› No state mutation") - } - }, + actionTransform: LoggerMiddleware.ActionTransform = .default, + actionPrinter: LoggerMiddleware.ActionLogger = .osLog, + stateDiffTransform: LoggerMiddleware.StateDiffTransform = .diff(), + stateDiffPrinter: LoggerMiddleware.StateLogger = .osLog, queue: DispatchQueue = .main ) -> LoggerMiddleware { LoggerMiddleware( @@ -40,17 +28,17 @@ public final class LoggerMiddleware: Middleware where M.StateType private let middleware: M private let queue: DispatchQueue private var getState: GetState? - private let actionTransform: (InputActionType, ActionSource) -> String - private let actionPrinter: (String) -> Void - private let stateDiffTransform: (StateType?, StateType) -> String? - private let stateDiffPrinter: (String?) -> Void + private let actionTransform: ActionTransform + private let actionPrinter: ActionLogger + private let stateDiffTransform: StateDiffTransform + private let stateDiffPrinter: StateLogger init( _ middleware: M, - actionTransform: @escaping (InputActionType, ActionSource) -> String, - actionPrinter: @escaping (String) -> Void, - stateDiffTransform: @escaping (StateType?, StateType) -> String?, - stateDiffPrinter: @escaping (String?) -> Void, + actionTransform: ActionTransform, + actionPrinter: ActionLogger, + stateDiffTransform: StateDiffTransform, + stateDiffPrinter: StateLogger, queue: DispatchQueue ) { self.middleware = middleware @@ -77,9 +65,9 @@ public final class LoggerMiddleware: Middleware where M.StateType let stateAfter = self.getState?() else { return } self.queue.async { - let actionMessage = self.actionTransform(action, dispatcher) - self.actionPrinter(actionMessage) - self.stateDiffPrinter(self.stateDiffTransform(stateBefore, stateAfter)) + let actionMessage = self.actionTransform.transform(action: action, source: dispatcher) + self.actionPrinter.log(action: actionMessage) + self.stateDiffPrinter.log(state: self.stateDiffTransform.transform(oldState: stateBefore, newState: stateAfter)) } } } @@ -87,22 +75,10 @@ public final class LoggerMiddleware: Middleware where M.StateType extension LoggerMiddleware { public static func `default`( - actionTransform: @escaping (InputActionType, ActionSource) -> String = { - "\nšŸ•¹ \($0)\nšŸŽŖ \($1.file.split(separator: "/").last ?? ""):\($1.line) \($1.function)" - }, - actionPrinter: @escaping (String) -> Void = { os_log(.debug, log: .default, "%{PUBLIC}@", $0) }, - stateDiffTransform: @escaping (StateType?, StateType) -> String? = { - let stateBefore = dumpToString($0) - let stateAfter = dumpToString($1) - return Difference.diff(old: stateBefore, new: stateAfter, linesOfContext: 2, prefixLines: "šŸ› ") - }, - stateDiffPrinter: @escaping (String?) -> Void = { state in - if let state = state { - os_log(.debug, log: .default, "%{PUBLIC}@", state) - } else { - os_log(.debug, log: .default, "%{PUBLIC}@", "šŸ› No state mutation") - } - }, + actionTransform: LoggerMiddleware>.ActionTransform = .default, + actionPrinter: LoggerMiddleware>.ActionLogger = .osLog, + stateDiffTransform: LoggerMiddleware>.StateDiffTransform = .diff(), + stateDiffPrinter: LoggerMiddleware>.StateLogger = .osLog, queue: DispatchQueue = .main ) -> LoggerMiddleware> { .init( @@ -115,3 +91,102 @@ extension LoggerMiddleware { ) } } + +// MARK: - State +// MARK: State Logger +extension LoggerMiddleware { + public enum StateLogger { + case osLog + case file(URL) + case custom((String?) -> Void) + + func log(state: String?) { + switch self { + case .osLog: LoggerMiddleware.osLog(state: state) + case let .file(url): LoggerMiddleware.fileLog(state: state, to: url) + case let .custom(closure): closure(state) + } + } + } + + private static func osLog(state: String?) { + if let possibleStateChanges = state { + os_log(.debug, log: .default, "%{PUBLIC}@", possibleStateChanges) + } else { + os_log(.debug, log: .default, "%{PUBLIC}@", "šŸ› No state mutation") + } + } + + private static func fileLog(state: String?, to fileURL: URL) { + if let possibleStateChanges = state { + try? possibleStateChanges.write(toFile: fileURL.absoluteString, atomically: false, encoding: .utf8) + } else { + try? "šŸ› No state mutation".write(toFile: fileURL.absoluteString, atomically: false, encoding: .utf8) + } + } +} + +// MARK: State Diff Transform +extension LoggerMiddleware { + public enum StateDiffTransform { + case diff(linesOfContext: Int = 2, prefixLines: String = "šŸ› ") + case newStateOnly + case custom((StateType?, StateType) -> String?) + + func transform(oldState: StateType?, newState: StateType) -> String? { + switch self { + case let .diff(linesOfContext, prefixLines): + let stateBefore = dumpToString(oldState) + let stateAfter = dumpToString(newState) + return Difference.diff(old: stateBefore, new: stateAfter, linesOfContext: linesOfContext, prefixLines: prefixLines) + case .newStateOnly: + return dumpToString(newState) + case let .custom(closure): + return closure(oldState, newState) + } + } + } +} + +// MARK: - Action +// MARK: Action Logger +extension LoggerMiddleware { + public enum ActionLogger { + case osLog + case file(URL) + case custom((String) -> Void) + + func log(action: String) { + switch self { + case .osLog: LoggerMiddleware.osLog(action: action) + case let .file(url): LoggerMiddleware.fileLog(action: action, to: url) + case let .custom(closure): closure(action) + } + } + } + + private static func osLog(action: String) { + os_log(.debug, log: .default, "%{PUBLIC}@", action) + } + + private static func fileLog(action: String, to fileURL: URL) -> Void { + try? action.write(toFile: fileURL.absoluteString, atomically: false, encoding: .utf8) + } +} + +// MARK: Action Transform +extension LoggerMiddleware { + public enum ActionTransform { + case `default` + case actionNameOnly + case custom((InputActionType, ActionSource) -> String) + + func transform(action: InputActionType, source: ActionSource) -> String { + switch self { + case .default: return "\nšŸ•¹ \(action)\nšŸŽŖ \(source.file.split(separator: "/").last ?? ""):\(source.line) \(source.function)" + case .actionNameOnly: return "\(action)" + case let .custom(closure): return closure(action, source) + } + } + } +} From 88738ac00c15b1662b0e41799da5f1b87fbd1a2f Mon Sep 17 00:00:00 2001 From: Luiz Rodrigo Martins Barbosa Date: Tue, 8 Dec 2020 18:24:09 +0100 Subject: [PATCH 2/2] Improve default string formatting --- .../LoggerMiddleware/LoggerMiddleware.swift | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/Sources/LoggerMiddleware/LoggerMiddleware.swift b/Sources/LoggerMiddleware/LoggerMiddleware.swift index 92b40b5..7c56bbd 100644 --- a/Sources/LoggerMiddleware/LoggerMiddleware.swift +++ b/Sources/LoggerMiddleware/LoggerMiddleware.swift @@ -4,7 +4,7 @@ import SwiftRex extension Middleware where StateType: Equatable { public func logger( - actionTransform: LoggerMiddleware.ActionTransform = .default, + actionTransform: LoggerMiddleware.ActionTransform = .default(), actionPrinter: LoggerMiddleware.ActionLogger = .osLog, stateDiffTransform: LoggerMiddleware.StateDiffTransform = .diff(), stateDiffPrinter: LoggerMiddleware.StateLogger = .osLog, @@ -75,7 +75,7 @@ public final class LoggerMiddleware: Middleware where M.StateType extension LoggerMiddleware { public static func `default`( - actionTransform: LoggerMiddleware>.ActionTransform = .default, + actionTransform: LoggerMiddleware>.ActionTransform = .default(), actionPrinter: LoggerMiddleware>.ActionLogger = .osLog, stateDiffTransform: LoggerMiddleware>.StateDiffTransform = .diff(), stateDiffPrinter: LoggerMiddleware>.StateLogger = .osLog, @@ -98,9 +98,9 @@ extension LoggerMiddleware { public enum StateLogger { case osLog case file(URL) - case custom((String?) -> Void) + case custom((String) -> Void) - func log(state: String?) { + func log(state: String) { switch self { case .osLog: LoggerMiddleware.osLog(state: state) case let .file(url): LoggerMiddleware.fileLog(state: state, to: url) @@ -109,20 +109,12 @@ extension LoggerMiddleware { } } - private static func osLog(state: String?) { - if let possibleStateChanges = state { - os_log(.debug, log: .default, "%{PUBLIC}@", possibleStateChanges) - } else { - os_log(.debug, log: .default, "%{PUBLIC}@", "šŸ› No state mutation") - } + private static func osLog(state: String) { + os_log(.debug, log: .default, "%{PUBLIC}@", state) } - private static func fileLog(state: String?, to fileURL: URL) { - if let possibleStateChanges = state { - try? possibleStateChanges.write(toFile: fileURL.absoluteString, atomically: false, encoding: .utf8) - } else { - try? "šŸ› No state mutation".write(toFile: fileURL.absoluteString, atomically: false, encoding: .utf8) - } + private static func fileLog(state: String, to fileURL: URL) { + try? state.write(toFile: fileURL.absoluteString, atomically: false, encoding: .utf8) } } @@ -131,14 +123,15 @@ extension LoggerMiddleware { public enum StateDiffTransform { case diff(linesOfContext: Int = 2, prefixLines: String = "šŸ› ") case newStateOnly - case custom((StateType?, StateType) -> String?) + case custom((StateType?, StateType) -> String) - func transform(oldState: StateType?, newState: StateType) -> String? { + func transform(oldState: StateType?, newState: StateType) -> String { switch self { case let .diff(linesOfContext, prefixLines): let stateBefore = dumpToString(oldState) let stateAfter = dumpToString(newState) return Difference.diff(old: stateBefore, new: stateAfter, linesOfContext: linesOfContext, prefixLines: prefixLines) + ?? "\(prefixLines) No state mutation" case .newStateOnly: return dumpToString(newState) case let .custom(closure): @@ -177,15 +170,18 @@ extension LoggerMiddleware { // MARK: Action Transform extension LoggerMiddleware { public enum ActionTransform { - case `default` + case `default`(actionPrefix: String = "\nšŸ•¹ ", sourcePrefix: String = "\nšŸŽŖ ") case actionNameOnly case custom((InputActionType, ActionSource) -> String) func transform(action: InputActionType, source: ActionSource) -> String { switch self { - case .default: return "\nšŸ•¹ \(action)\nšŸŽŖ \(source.file.split(separator: "/").last ?? ""):\(source.line) \(source.function)" - case .actionNameOnly: return "\(action)" - case let .custom(closure): return closure(action, source) + case let .default(actionPrefix, sourcePrefix): + return "\(actionPrefix)\(action)\(sourcePrefix)\(source.file.split(separator: "/").last ?? ""):\(source.line) \(source.function)" + case .actionNameOnly: + return "\(action)" + case let .custom(closure): + return closure(action, source) } } }