Skip to content

Commit 95a4c56

Browse files
committed
Add file logger
1 parent 6fdad87 commit 95a4c56

File tree

1 file changed

+118
-43
lines changed

1 file changed

+118
-43
lines changed

Sources/LoggerMiddleware/LoggerMiddleware.swift

Lines changed: 118 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,10 @@ import SwiftRex
44

55
extension Middleware where StateType: Equatable {
66
public func logger(
7-
actionTransform: @escaping (InputActionType, ActionSource) -> String = {
8-
"\n🕹 \($0)\n🎪 \($1.file.split(separator: "/").last ?? ""):\($1.line) \($1.function)"
9-
},
10-
actionPrinter: @escaping (String) -> Void = { os_log(.debug, log: .default, "%{PUBLIC}@", $0) },
11-
stateDiffTransform: @escaping (StateType?, StateType) -> String? = {
12-
let stateBefore = dumpToString($0)
13-
let stateAfter = dumpToString($1)
14-
return Difference.diff(old: stateBefore, new: stateAfter, linesOfContext: 2, prefixLines: "🏛 ")
15-
},
16-
stateDiffPrinter: @escaping (String?) -> Void = { state in
17-
if let state = state {
18-
os_log(.debug, log: .default, "%{PUBLIC}@", state)
19-
} else {
20-
os_log(.debug, log: .default, "%{PUBLIC}@", "🏛 No state mutation")
21-
}
22-
},
7+
actionTransform: LoggerMiddleware<Self>.ActionTransform = .default,
8+
actionPrinter: LoggerMiddleware<Self>.ActionLogger = .osLog,
9+
stateDiffTransform: LoggerMiddleware<Self>.StateDiffTransform = .diff(),
10+
stateDiffPrinter: LoggerMiddleware<Self>.StateLogger = .osLog,
2311
queue: DispatchQueue = .main
2412
) -> LoggerMiddleware<Self> {
2513
LoggerMiddleware(
@@ -40,17 +28,17 @@ public final class LoggerMiddleware<M: Middleware>: Middleware where M.StateType
4028
private let middleware: M
4129
private let queue: DispatchQueue
4230
private var getState: GetState<StateType>?
43-
private let actionTransform: (InputActionType, ActionSource) -> String
44-
private let actionPrinter: (String) -> Void
45-
private let stateDiffTransform: (StateType?, StateType) -> String?
46-
private let stateDiffPrinter: (String?) -> Void
31+
private let actionTransform: ActionTransform
32+
private let actionPrinter: ActionLogger
33+
private let stateDiffTransform: StateDiffTransform
34+
private let stateDiffPrinter: StateLogger
4735

4836
init(
4937
_ middleware: M,
50-
actionTransform: @escaping (InputActionType, ActionSource) -> String,
51-
actionPrinter: @escaping (String) -> Void,
52-
stateDiffTransform: @escaping (StateType?, StateType) -> String?,
53-
stateDiffPrinter: @escaping (String?) -> Void,
38+
actionTransform: ActionTransform,
39+
actionPrinter: ActionLogger,
40+
stateDiffTransform: StateDiffTransform,
41+
stateDiffPrinter: StateLogger,
5442
queue: DispatchQueue
5543
) {
5644
self.middleware = middleware
@@ -77,32 +65,20 @@ public final class LoggerMiddleware<M: Middleware>: Middleware where M.StateType
7765
let stateAfter = self.getState?() else { return }
7866

7967
self.queue.async {
80-
let actionMessage = self.actionTransform(action, dispatcher)
81-
self.actionPrinter(actionMessage)
82-
self.stateDiffPrinter(self.stateDiffTransform(stateBefore, stateAfter))
68+
let actionMessage = self.actionTransform.transform(action: action, source: dispatcher)
69+
self.actionPrinter.log(action: actionMessage)
70+
self.stateDiffPrinter.log(state: self.stateDiffTransform.transform(oldState: stateBefore, newState: stateAfter))
8371
}
8472
}
8573
}
8674
}
8775

8876
extension LoggerMiddleware {
8977
public static func `default`(
90-
actionTransform: @escaping (InputActionType, ActionSource) -> String = {
91-
"\n🕹 \($0)\n🎪 \($1.file.split(separator: "/").last ?? ""):\($1.line) \($1.function)"
92-
},
93-
actionPrinter: @escaping (String) -> Void = { os_log(.debug, log: .default, "%{PUBLIC}@", $0) },
94-
stateDiffTransform: @escaping (StateType?, StateType) -> String? = {
95-
let stateBefore = dumpToString($0)
96-
let stateAfter = dumpToString($1)
97-
return Difference.diff(old: stateBefore, new: stateAfter, linesOfContext: 2, prefixLines: "🏛 ")
98-
},
99-
stateDiffPrinter: @escaping (String?) -> Void = { state in
100-
if let state = state {
101-
os_log(.debug, log: .default, "%{PUBLIC}@", state)
102-
} else {
103-
os_log(.debug, log: .default, "%{PUBLIC}@", "🏛 No state mutation")
104-
}
105-
},
78+
actionTransform: LoggerMiddleware<IdentityMiddleware<InputActionType, OutputActionType, StateType>>.ActionTransform = .default,
79+
actionPrinter: LoggerMiddleware<IdentityMiddleware<InputActionType, OutputActionType, StateType>>.ActionLogger = .osLog,
80+
stateDiffTransform: LoggerMiddleware<IdentityMiddleware<InputActionType, OutputActionType, StateType>>.StateDiffTransform = .diff(),
81+
stateDiffPrinter: LoggerMiddleware<IdentityMiddleware<InputActionType, OutputActionType, StateType>>.StateLogger = .osLog,
10682
queue: DispatchQueue = .main
10783
) -> LoggerMiddleware<IdentityMiddleware<InputActionType, OutputActionType, StateType>> {
10884
.init(
@@ -115,3 +91,102 @@ extension LoggerMiddleware {
11591
)
11692
}
11793
}
94+
95+
// MARK: - State
96+
// MARK: State Logger
97+
extension LoggerMiddleware {
98+
public enum StateLogger {
99+
case osLog
100+
case file(URL)
101+
case custom((String?) -> Void)
102+
103+
func log(state: String?) {
104+
switch self {
105+
case .osLog: LoggerMiddleware.osLog(state: state)
106+
case let .file(url): LoggerMiddleware.fileLog(state: state, to: url)
107+
case let .custom(closure): closure(state)
108+
}
109+
}
110+
}
111+
112+
private static func osLog(state: String?) {
113+
if let possibleStateChanges = state {
114+
os_log(.debug, log: .default, "%{PUBLIC}@", possibleStateChanges)
115+
} else {
116+
os_log(.debug, log: .default, "%{PUBLIC}@", "🏛 No state mutation")
117+
}
118+
}
119+
120+
private static func fileLog(state: String?, to fileURL: URL) {
121+
if let possibleStateChanges = state {
122+
try? possibleStateChanges.write(toFile: fileURL.absoluteString, atomically: false, encoding: .utf8)
123+
} else {
124+
try? "🏛 No state mutation".write(toFile: fileURL.absoluteString, atomically: false, encoding: .utf8)
125+
}
126+
}
127+
}
128+
129+
// MARK: State Diff Transform
130+
extension LoggerMiddleware {
131+
public enum StateDiffTransform {
132+
case diff(linesOfContext: Int = 2, prefixLines: String = "🏛 ")
133+
case newStateOnly
134+
case custom((StateType?, StateType) -> String?)
135+
136+
func transform(oldState: StateType?, newState: StateType) -> String? {
137+
switch self {
138+
case let .diff(linesOfContext, prefixLines):
139+
let stateBefore = dumpToString(oldState)
140+
let stateAfter = dumpToString(newState)
141+
return Difference.diff(old: stateBefore, new: stateAfter, linesOfContext: linesOfContext, prefixLines: prefixLines)
142+
case .newStateOnly:
143+
return dumpToString(newState)
144+
case let .custom(closure):
145+
return closure(oldState, newState)
146+
}
147+
}
148+
}
149+
}
150+
151+
// MARK: - Action
152+
// MARK: Action Logger
153+
extension LoggerMiddleware {
154+
public enum ActionLogger {
155+
case osLog
156+
case file(URL)
157+
case custom((String) -> Void)
158+
159+
func log(action: String) {
160+
switch self {
161+
case .osLog: LoggerMiddleware.osLog(action: action)
162+
case let .file(url): LoggerMiddleware.fileLog(action: action, to: url)
163+
case let .custom(closure): closure(action)
164+
}
165+
}
166+
}
167+
168+
private static func osLog(action: String) {
169+
os_log(.debug, log: .default, "%{PUBLIC}@", action)
170+
}
171+
172+
private static func fileLog(action: String, to fileURL: URL) -> Void {
173+
try? action.write(toFile: fileURL.absoluteString, atomically: false, encoding: .utf8)
174+
}
175+
}
176+
177+
// MARK: Action Transform
178+
extension LoggerMiddleware {
179+
public enum ActionTransform {
180+
case `default`
181+
case actionNameOnly
182+
case custom((InputActionType, ActionSource) -> String)
183+
184+
func transform(action: InputActionType, source: ActionSource) -> String {
185+
switch self {
186+
case .default: return "\n🕹 \(action)\n🎪 \(source.file.split(separator: "/").last ?? ""):\(source.line) \(source.function)"
187+
case .actionNameOnly: return "\(action)"
188+
case let .custom(closure): return closure(action, source)
189+
}
190+
}
191+
}
192+
}

0 commit comments

Comments
 (0)