Uncoupled DiskLogger from FileRotate

This commit is contained in:
Wojciech Nagrodzki 2018-08-26 13:30:53 +02:00
parent d333992ca6
commit 1144d6a90f
Signed by: wnagrodzki
GPG key ID: E9D0EB0302264569
2 changed files with 41 additions and 11 deletions

View file

@ -24,6 +24,30 @@
import Foundation import Foundation
/// Allows log files rotation.
protocol Logrotate {
/// Rotates log files `rotations` number of times.
///
/// First deletes file at `<fileURL>.<rotations>`.
/// Next moves files located at:
///
/// `<fileURL>, <fileURL>.1, <fileURL>.2 ... <fileURL>.<rotations - 1>`
///
/// to `<fileURL>.1, <fileURL>.2 ... <fileURL>.<rotations>`
func rotate() throws
}
protocol LogrotateFactory {
/// Returns newly initialized Logrotate instance.
///
/// - Parameters:
/// - fileURL: URL of the log file.
/// - rotations: Number of times log files are rotated before being removed.
func makeInstance(fileURL: URL, rotations: Int) -> Logrotate
}
/// Logger that writes messages into the file at specified URL with log rotation support. /// Logger that writes messages into the file at specified URL with log rotation support.
public final class DiskLogger: Logger { public final class DiskLogger: Logger {
@ -31,6 +55,7 @@ public final class DiskLogger: Logger {
private let fileSizeLimit: UInt64 private let fileSizeLimit: UInt64
private let rotations: Int private let rotations: Int
private let fileSystem: FileSystem private let fileSystem: FileSystem
private let logrotateFactory: LogrotateFactory
private let formatter: DateFormatter private let formatter: DateFormatter
private let queue = DispatchQueue(label: "com.wnagrodzki.DiskLogger", qos: .background, attributes: [], autoreleaseFrequency: .workItem, target: nil) private let queue = DispatchQueue(label: "com.wnagrodzki.DiskLogger", qos: .background, attributes: [], autoreleaseFrequency: .workItem, target: nil)
private var buffer = Data() private var buffer = Data()
@ -42,11 +67,16 @@ public final class DiskLogger: Logger {
/// - fileURL: URL of the log file. /// - fileURL: URL of the log file.
/// - fileSizeLimit: Maximum size log file can reach in bytes. Attempt to exceeding that limit triggers log files rotation. /// - fileSizeLimit: Maximum size log file can reach in bytes. Attempt to exceeding that limit triggers log files rotation.
/// - rotations: Number of times log files are rotated before being removed. /// - rotations: Number of times log files are rotated before being removed.
public init(fileURL: URL, fileSizeLimit: UInt64, rotations: Int, fileSystem: FileSystem) { public convenience init(fileURL: URL, fileSizeLimit: UInt64, rotations: Int) {
self.init(fileURL: fileURL, fileSizeLimit: fileSizeLimit, rotations: rotations, fileSystem: FileManager.default, logrotateFactory: FileRotateFactory())
}
init(fileURL: URL, fileSizeLimit: UInt64, rotations: Int, fileSystem: FileSystem, logrotateFactory: LogrotateFactory) {
self.fileURL = fileURL self.fileURL = fileURL
self.fileSizeLimit = fileSizeLimit self.fileSizeLimit = fileSizeLimit
self.rotations = rotations self.rotations = rotations
self.fileSystem = fileSystem self.fileSystem = fileSystem
self.logrotateFactory = logrotateFactory
formatter = DateFormatter() formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS" formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
formatter.timeZone = TimeZone(secondsFromGMT: 0) formatter.timeZone = TimeZone(secondsFromGMT: 0)
@ -99,7 +129,13 @@ public final class DiskLogger: Logger {
} }
private func rotateLogFiles() throws { private func rotateLogFiles() throws {
let logrotate = FileRotate(fileURL: fileURL, rotations: rotations, fileSystem: fileSystem) let logrotate = logrotateFactory.makeInstance(fileURL: fileURL, rotations: rotations)
try logrotate.rotate() try logrotate.rotate()
} }
} }
private class FileRotateFactory: LogrotateFactory {
func makeInstance(fileURL: URL, rotations: Int) -> Logrotate {
return FileRotate(fileURL: fileURL, rotations: rotations, fileSystem: FileManager.default)
}
}

View file

@ -24,7 +24,6 @@
import Foundation import Foundation
/// Allows log files rotation.
final class FileRotate { final class FileRotate {
private let fileURL: URL private let fileURL: URL
@ -42,15 +41,10 @@ final class FileRotate {
self.rotations = rotations self.rotations = rotations
self.fileSystem = fileSystem self.fileSystem = fileSystem
} }
}
extension FileRotate: Logrotate {
/// Rotates log files `rotations` number of times.
///
/// First deletes file at `<fileURL>.<rotations>`.
/// Next moves files located at:
///
/// `<fileURL>, <fileURL>.1, <fileURL>.2 ... <fileURL>.<rotations - 1>`
///
/// to `<fileURL>.1, <fileURL>.2 ... <fileURL>.<rotations>`
func rotate() throws { func rotate() throws {
let range = 1...rotations let range = 1...rotations
let pathExtensions = range.map { "\($0)" } let pathExtensions = range.map { "\($0)" }