diff --git a/Sources/Puree/Logger.swift b/Sources/Puree/Logger.swift index 624e0b0..77ad214 100644 --- a/Sources/Puree/Logger.swift +++ b/Sources/Puree/Logger.swift @@ -79,6 +79,12 @@ public final class Logger { } } + public func sendBufferedLogs() { + dispatchQueue.sync { + outputs.forEach { ($0 as? BufferedOutput)?.sendBufferedLogs() } + } + } + public func suspend() { dispatchQueue.sync { outputs.forEach { $0.suspend() } diff --git a/Sources/Puree/Output/BufferedOutput.swift b/Sources/Puree/Output/BufferedOutput.swift index 4bc9571..ca4e1d3 100644 --- a/Sources/Puree/Output/BufferedOutput.swift +++ b/Sources/Puree/Output/BufferedOutput.swift @@ -71,17 +71,13 @@ open class BufferedOutput: InstantiatableOutput { public func start() { reloadLogStore() - readWriteQueue.sync { - flush() - } + sendBufferedLogs() setUpTimer() } public func resume() { reloadLogStore() - readWriteQueue.sync { - flush() - } + sendBufferedLogs() setUpTimer() } @@ -100,19 +96,25 @@ open class BufferedOutput: InstantiatableOutput { logStore.add(log, for: storageGroup, completion: nil) if buffer.count >= logLimit { - flush() + writeBufferedLogs() } else if let logSizeLimit = configuration.chunkDataSizeLimit { let currentBufferedLogSize = buffer.reduce(0, { (size, log) -> Int in size + (log.userData?.count ?? 0) }) if currentBufferedLogSize >= logSizeLimit { - flush() + writeBufferedLogs() } } } } + public func sendBufferedLogs() { + readWriteQueue.sync { + writeBufferedLogs() + } + } + open func write(_ chunk: Chunk, completion: @escaping (Bool) -> Void) { completion(false) } @@ -138,12 +140,12 @@ open class BufferedOutput: InstantiatableOutput { if let lastFlushDate = lastFlushDate { if currentDate.timeIntervalSince(lastFlushDate) > flushInterval { readWriteQueue.async { - self.flush() + self.writeBufferedLogs() } } } else { readWriteQueue.async { - self.flush() + self.writeBufferedLogs() } } } @@ -165,7 +167,7 @@ open class BufferedOutput: InstantiatableOutput { } } - private func flush() { + private func writeBufferedLogs() { dispatchPrecondition(condition: .onQueue(readWriteQueue)) lastFlushDate = currentDate diff --git a/Tests/PureeTests/Output/BufferedOutputTests.swift b/Tests/PureeTests/Output/BufferedOutputTests.swift index 59859df..67ca584 100644 --- a/Tests/PureeTests/Output/BufferedOutputTests.swift +++ b/Tests/PureeTests/Output/BufferedOutputTests.swift @@ -63,6 +63,20 @@ class BufferedOutputTests: XCTestCase { XCTAssertEqual(output.calledWriteCount, 1) } + func testBufferedOutputSendBufferedLogs() { + output.configuration.logEntryCountLimit = 10 + + XCTAssertEqual(logStore.logs(for: "pv_TestingBufferedOutput").count, 0) + XCTAssertEqual(output.calledWriteCount, 0) + + output.emit(log: makeLog()) + output.sendBufferedLogs() + output.waitUntilCurrentQueuedJobFinished() + + XCTAssertEqual(logStore.logs(for: "pv_TestingBufferedOutput").count, 0) + XCTAssertEqual(output.calledWriteCount, 1) + } + func testBufferedOutputFlushedByInterval() { output.configuration.logEntryCountLimit = 10 output.configuration.flushInterval = 1 @@ -87,7 +101,7 @@ class BufferedOutputTests: XCTestCase { XCTAssertEqual(output.calledWriteCount, 0) output.writeCallback = { - XCTFail("flush should not be called") + XCTFail("writeBufferedLogs should not be called") } sleep(2) } @@ -291,6 +305,28 @@ class BufferedOutputAsyncTests: XCTestCase { XCTAssertEqual(output.calledWriteCount, 1) } + func testBufferedOutputSendBufferedLogs() { + output.configuration.logEntryCountLimit = 10 + + let expectation = self.expectation(description: "async writing") + output.writeCallback = { + expectation.fulfill() + } + output.waitUntilCurrentCompletionBlock = { [weak self] in + self?.wait(for: [expectation], timeout: 1.0) + } + + XCTAssertEqual(logStore.logs(for: "pv_TestingBufferedOutput").count, 0) + XCTAssertEqual(output.calledWriteCount, 0) + + output.emit(log: makeLog()) + output.sendBufferedLogs() + output.waitUntilCurrentQueuedJobFinished() + + XCTAssertEqual(logStore.logs(for: "pv_TestingBufferedOutput").count, 0) + XCTAssertEqual(output.calledWriteCount, 1) + } + func testBufferedOutputFlushedByInterval() { output.configuration.logEntryCountLimit = 10 output.configuration.flushInterval = 1 @@ -315,7 +351,7 @@ class BufferedOutputAsyncTests: XCTestCase { XCTAssertEqual(output.calledWriteCount, 0) output.writeCallback = { - XCTFail("flush should not be called") + XCTFail("writeBufferedLogs should not be called") } sleep(2) }