Skip to content

Commit 0061ffd

Browse files
committed
Auto delete outdated logs & fix unit test
1 parent ad2bc89 commit 0061ffd

File tree

3 files changed

+72
-21
lines changed

3 files changed

+72
-21
lines changed

Sources/Logger/Handlers/SerializedLogHandler.swift

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public final class SerializedLogHandler: LogHandler, LogPresentable {
1717
public var isEnabled: Bool = true
1818
public var filter: Filter?
1919
public let fileURL: URL
20+
public var autoDeleteOutdatedLogs = true
21+
public var outdatedLogDate = Date(timeIntervalSinceNow: -5 * 24 * 3600)
2022

2123
public var isClosed: Bool {
2224
db == nil
@@ -54,7 +56,7 @@ public final class SerializedLogHandler: LogHandler, LogPresentable {
5456
var stmt: OpaquePointer?
5557
let sql = """
5658
SELECT message, date, level, tag, file, line, column, function FROM Logs ORDER BY id DESC
57-
"""
59+
"""
5860

5961
if sqlite3_prepare_v2(db, sql, -1, &stmt, nil) == SQLITE_OK {
6062
while sqlite3_step(stmt) == SQLITE_ROW {
@@ -126,12 +128,20 @@ public final class SerializedLogHandler: LogHandler, LogPresentable {
126128
column INTEGER,
127129
function TEXT
128130
)
129-
"""
131+
"""
130132

131133
if sqlite3_exec(db, sql, nil, nil, nil) != SQLITE_OK {
132134
let message = logErrorMessage()
133135
throw HandlerError(reason: .databaseOpenFailed, message: message)
134136
}
137+
138+
Logger.logQueue.asyncAfter(deadline: .now() + 5) { [weak self] in
139+
guard let self = self else { return }
140+
141+
if self.autoDeleteOutdatedLogs {
142+
self.deleteOutdatedLogs()
143+
}
144+
}
135145
}
136146

137147
public func close() throws {
@@ -159,23 +169,46 @@ public final class SerializedLogHandler: LogHandler, LogPresentable {
159169
\(log.column),
160170
'\(encode(log.function))'
161171
)
162-
"""
172+
"""
163173

164174
if sqlite3_exec(db, sql, nil, nil, nil) != SQLITE_OK {
165175
logErrorMessage()
166176
}
167177
}
168178

169-
public func truncate() throws {
179+
public func deleteAllLogs() {
180+
Logger.logQueue.async { [weak self] in
181+
self?._deleteAllLogs()
182+
}
183+
}
184+
185+
private func _deleteAllLogs() {
170186
guard let db = db else { return }
171187

172188
let sql = """
173189
DELETE FROM Logs
174-
"""
190+
"""
175191

176192
if sqlite3_exec(db, sql, nil, nil, nil) != SQLITE_OK {
177-
let message = logErrorMessage()
178-
throw HandlerError(reason: .databaseTruncateFailed, message: message)
193+
logErrorMessage()
194+
}
195+
}
196+
197+
public func deleteOutdatedLogs() {
198+
Logger.logQueue.async { [weak self] in
199+
self?._deleteOutdatedLogs()
200+
}
201+
}
202+
203+
private func _deleteOutdatedLogs() {
204+
guard let db = db else { return }
205+
206+
let sql = """
207+
DELETE FROM Logs WHERE date < \(outdatedLogDate.timeIntervalSince1970)
208+
"""
209+
210+
if sqlite3_exec(db, sql, nil, nil, nil) != SQLITE_OK {
211+
logErrorMessage()
179212
}
180213
}
181214

Sources/LoggerDemo/main.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ import Foundation
1111
import Logger
1212

1313
let logger = Logger()
14+
logger.add(trigger: CrashLogTrigger.shared)
1415
logger.add(handler: ConsoleLogHandler())
16+
logger.add(handler: try! SerializedLogHandler(fileURL: URL(fileURLWithPath: "/Users/Madimo/Desktop/logs.db")))
1517

1618
logger.info("Hello World!")
19+
20+
NSArray().object(at: 1)

Tests/LoggerTests/LoggerTests.swift

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,19 @@ import XCTest
1212

1313
final class LoggerTests: XCTestCase {
1414

15-
// func wait(_ logger: Logger, timeout: TimeInterval, file: String = #file, line: Int = #line) {
16-
// let expectation = XCTestExpectation()
17-
// logger.dispatchQueue.async {
18-
// expectation.fulfill()
19-
// }
20-
//
21-
// switch XCTWaiter.wait(for: [expectation], timeout: timeout) {
22-
// case .timedOut:
23-
// recordFailure(withDescription: "Wait for logger timed out.", inFile: file, atLine: line, expected: true)
24-
// default:
25-
// break
26-
// }
27-
// }
15+
func waitLogQueue(timeout: TimeInterval = 10, file: String = #file, line: Int = #line) {
16+
let expectation = XCTestExpectation()
17+
Logger.logQueue.async {
18+
expectation.fulfill()
19+
}
20+
21+
switch XCTWaiter.wait(for: [expectation], timeout: timeout) {
22+
case .timedOut:
23+
recordFailure(withDescription: "Wait for logger timed out.", inFile: file, atLine: line, expected: true)
24+
default:
25+
break
26+
}
27+
}
2828

2929
func testAddAndRemoveLogHandler() {
3030
let logger = Logger()
@@ -208,6 +208,8 @@ final class LoggerTests: XCTestCase {
208208

209209
do {
210210
let log = logger.debug("This is a log message.")
211+
waitLogQueue()
212+
211213
XCTAssertEqual(serializedLogHandler.logs.count, 1)
212214
XCTAssertEqual(serializedLogHandler.logs[0].message, log.message)
213215
XCTAssertEqual(Int(serializedLogHandler.logs[0].date.timeIntervalSince1970), Int(log.date.timeIntervalSince1970))
@@ -221,31 +223,41 @@ final class LoggerTests: XCTestCase {
221223

222224
do {
223225
let log = logger.info("This is another\n\nlog message.")
226+
waitLogQueue()
227+
224228
XCTAssertEqual(serializedLogHandler.logs[0].message, log.message)
225229
}
226230

227231
do {
228232
let log = logger.info("🎉 This is a log message contains Emoji 😄.")
233+
waitLogQueue()
234+
229235
XCTAssertEqual(serializedLogHandler.logs[0].message, log.message)
230236
}
231237

232238
do {
233239
let log = logger.info("#//This is a log message contains '''?\"./*")
240+
waitLogQueue()
241+
234242
XCTAssertEqual(serializedLogHandler.logs[0].message, log.message)
235243
}
236244

237245
do {
238246
let log = logger.info("This is a log message contains 中文")
247+
waitLogQueue()
248+
239249
XCTAssertEqual(serializedLogHandler.logs[0].message, log.message)
240250
}
241251

242-
try serializedLogHandler.truncate()
252+
serializedLogHandler.deleteAllLogs()
253+
waitLogQueue()
243254
XCTAssertTrue(serializedLogHandler.logs.isEmpty)
244255

245256
try serializedLogHandler.close()
246257
XCTAssertTrue(serializedLogHandler.logs.isEmpty)
247258

248259
logger.info("This is another log message.")
260+
waitLogQueue()
249261
try serializedLogHandler.open()
250262
XCTAssertTrue(serializedLogHandler.logs.isEmpty)
251263
}
@@ -257,6 +269,7 @@ final class LoggerTests: XCTestCase {
257269
logger.add(handler: fileLoghandler)
258270

259271
var log = logger.log("This is a message.", level: .debug)
272+
waitLogQueue()
260273
fileLoghandler.close()
261274

262275
var data = try XCTUnwrap(FileManager.default.contents(atPath: url.path))
@@ -266,6 +279,7 @@ final class LoggerTests: XCTestCase {
266279

267280
try fileLoghandler.open()
268281
log = logger.log("This is another message.", level: .debug)
282+
waitLogQueue()
269283
fileLoghandler.close()
270284

271285
data = try XCTUnwrap(FileManager.default.contents(atPath: url.path))

0 commit comments

Comments
 (0)