From 733be701b45d75191582c86583c0da291fe5b5a5 Mon Sep 17 00:00:00 2001 From: Dave Wood Date: Tue, 4 Feb 2020 06:21:00 -0500 Subject: [PATCH 1/6] Add missing convenience methods for the new log levels (thanks @hk05, fixes #296) --- Sources/XCGLogger/XCGLogger.swift | 336 ++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) diff --git a/Sources/XCGLogger/XCGLogger.swift b/Sources/XCGLogger/XCGLogger.swift index 44ba76d7..fdd2c114 100644 --- a/Sources/XCGLogger/XCGLogger.swift +++ b/Sources/XCGLogger/XCGLogger.swift @@ -677,6 +677,95 @@ open class XCGLogger: CustomDebugStringConvertible { self.logln(.info, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) } + // MARK: * Notice + /// Log something at the Notice log level. This format of notice() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func notice(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.notice, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.default.noMessageClosure) + } + + /// Log something at the Notice log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func notice(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.notice, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Notice log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open class func notice(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(.notice, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Notice log level. This format of notice() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func notice(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.notice, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.noMessageClosure) + } + + /// Log something at the Notice log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func notice(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.notice, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Notice log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open func notice(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.logln(.notice, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + // MARK: * Warning /// Log something at the Warning log level. This format of warning() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. /// @@ -944,6 +1033,184 @@ open class XCGLogger: CustomDebugStringConvertible { self.logln(.severe, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) } + // MARK: * Alert + /// Log something at the Alert log level. This format of alert() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func alert(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.alert, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.default.noMessageClosure) + } + + /// Log something at the Alert log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func alert(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.alert, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Alert log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open class func alert(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(.alert, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Alert log level. This format of alert() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func alert(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.alert, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.noMessageClosure) + } + + /// Log something at the Alert log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func alert(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.alert, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Alert log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open func alert(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.logln(.alert, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + // MARK: * Emergency + /// Log something at the Emergency log level. This format of emergency() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func emergency(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.emergency, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.default.noMessageClosure) + } + + /// Log something at the Emergency log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func emergency(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.emergency, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Emergency log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open class func emergency(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(.emergency, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Emergency log level. This format of emergency() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func emergency(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.emergency, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.noMessageClosure) + } + + /// Log something at the Emergency log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func emergency(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.emergency, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Emergency log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open func emergency(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.logln(.emergency, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + // MARK: - Exec Methods // MARK: * Verbose /// Execute some code only when at the Verbose log level. @@ -1014,6 +1281,29 @@ open class XCGLogger: CustomDebugStringConvertible { self.exec(XCGLogger.Level.info, closure: closure) } + // MARK: * Notice + /// Execute some code only when at the Notice or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open class func noticeExec(_ closure: () -> () = {}) { + self.default.exec(XCGLogger.Level.notice, closure: closure) + } + + /// Execute some code only when at the Notice or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open func noticeExec(_ closure: () -> () = {}) { + self.exec(XCGLogger.Level.notice, closure: closure) + } + // MARK: * Warning /// Execute some code only when at the Warning or lower log level. /// @@ -1083,6 +1373,52 @@ open class XCGLogger: CustomDebugStringConvertible { self.exec(XCGLogger.Level.severe, closure: closure) } + // MARK: * Alert + /// Execute some code only when at the Alert or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open class func alertExec(_ closure: () -> () = {}) { + self.default.exec(XCGLogger.Level.alert, closure: closure) + } + + /// Execute some code only when at the Alert or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open func alertExec(_ closure: () -> () = {}) { + self.exec(XCGLogger.Level.alert, closure: closure) + } + + // MARK: * Emergency + /// Execute some code only when at the Emergency or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open class func emergencyExec(_ closure: () -> () = {}) { + self.default.exec(XCGLogger.Level.emergency, closure: closure) + } + + /// Execute some code only when at the Emergency or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open func emergencyExec(_ closure: () -> () = {}) { + self.exec(XCGLogger.Level.emergency, closure: closure) + } + // MARK: - Log destination methods /// Get the destination with the specified identifier. /// From 50cb1a4d692799cefd07eea92c1268dfd28bca51 Mon Sep 17 00:00:00 2001 From: Dave Wood Date: Tue, 4 Feb 2020 06:21:54 -0500 Subject: [PATCH 2/6] Adds new log levels to the demo projects --- .../iOSDemo/Base.lproj/Main.storyboard | 156 ++++++++++++++---- DemoApps/iOSDemo/iOSDemo/ViewController.swift | 49 +++++- .../InterfaceController.swift | 12 ++ .../Base.lproj/Interface.storyboard | 25 ++- .../macOSDemo/macOSDemo/AppDelegate.swift | 49 +++++- .../macOSDemo/Base.lproj/MainMenu.xib | 96 ++++++++--- .../tvOSDemo/Base.lproj/Main.storyboard | 82 +++++---- .../tvOSDemo/tvOSDemo/ViewController.swift | 12 ++ 8 files changed, 378 insertions(+), 103 deletions(-) diff --git a/DemoApps/iOSDemo/iOSDemo/Base.lproj/Main.storyboard b/DemoApps/iOSDemo/iOSDemo/Base.lproj/Main.storyboard index f753c427..2ea33668 100644 --- a/DemoApps/iOSDemo/iOSDemo/Base.lproj/Main.storyboard +++ b/DemoApps/iOSDemo/iOSDemo/Base.lproj/Main.storyboard @@ -1,11 +1,9 @@ - - - - + + - + @@ -22,7 +20,7 @@ - - + + @@ -40,7 +38,7 @@ + + - + - - + @@ -231,32 +294,47 @@ + + + - + + + + + + + + + - + + + - + + + @@ -264,26 +342,32 @@ + + - - + + + + + + - + diff --git a/DemoApps/iOSDemo/iOSDemo/ViewController.swift b/DemoApps/iOSDemo/iOSDemo/ViewController.swift index dbceebbc..4872bf19 100644 --- a/DemoApps/iOSDemo/iOSDemo/ViewController.swift +++ b/DemoApps/iOSDemo/iOSDemo/ViewController.swift @@ -49,6 +49,14 @@ class ViewController: UIViewController { } } + @IBAction func noticeButtonTouchUpInside(_ sender: AnyObject) { + log.notice("Notice button tapped") + log.notice { + // add expensive code required only for logging, then return an optional String + return "Executed notice code block" // or nil + } + } + @IBAction func warningButtonTouchUpInside(_ sender: AnyObject) { log.warning("Warning button tapped") log.warning { @@ -73,6 +81,22 @@ class ViewController: UIViewController { } } + @IBAction func alertButtonTouchUpInside(_ sender: AnyObject) { + log.alert("Alert button tapped") + log.alert { + // add expensive code required only for logging, then return an optional String + return "Executed alert code block" // or nil + } + } + + @IBAction func emergencyButtonTouchUpInside(_ sender: AnyObject) { + log.emergency("Emergency button tapped") + log.emergency { + // add expensive code required only for logging, then return an optional String + return "Executed emergency code block" // or nil + } + } + @IBAction func verboseSensitiveButtonTouchUpInside(_ sender: AnyObject) { // Can add multiple Dev/Tag objects together using the | operator log.verbose("Verbose (Sensitive) button tapped", userInfo: Dev.dave | Tag.sensitive) @@ -87,6 +111,10 @@ class ViewController: UIViewController { log.info("Info (Sensitive) button tapped", userInfo: Dev.dave | Tag.sensitive | Tag("informative")) } + @IBAction func noticeSensitiveButtonTouchUpInside(_ sender: AnyObject) { + log.notice("Notice (Sensitive) button tapped", userInfo: Dev.dave | Tag.sensitive) + } + @IBAction func warningSensitiveButtonTouchUpInside(_ sender: AnyObject) { // Can add a bunch of Dev/Tag objects log.warning("Warning (Sensitive) button tapped", userInfo: Dev.sabby | Dev.dave | Tag.sensitive | Tag.ui) @@ -104,6 +132,14 @@ class ViewController: UIViewController { log.severe("Severe (Sensitive) button tapped", userInfo: Tag.sensitive.dictionary) } + @IBAction func alertSensitiveButtonTouchUpInside(_ sender: AnyObject) { + log.alert("Alert (Sensitive) button tapped", userInfo: Dev.dave | Tag.sensitive) + } + + @IBAction func emergencySensitiveButtonTouchUpInside(_ sender: AnyObject) { + log.emergency("Emergency (Sensitive) button tapped", userInfo: Dev.dave | Tag.sensitive) + } + @IBAction func logLevelSliderValueChanged(_ sender: AnyObject) { var logLevel: XCGLogger.Level = .verbose @@ -117,14 +153,23 @@ class ViewController: UIViewController { logLevel = .info } else if (3 <= logLevelSlider.value && logLevelSlider.value < 4) { - logLevel = .warning + logLevel = .notice } else if (4 <= logLevelSlider.value && logLevelSlider.value < 5) { - logLevel = .error + logLevel = .warning } else if (5 <= logLevelSlider.value && logLevelSlider.value < 6) { + logLevel = .error + } + else if (6 <= logLevelSlider.value && logLevelSlider.value < 7) { logLevel = .severe } + else if (7 <= logLevelSlider.value && logLevelSlider.value < 8) { + logLevel = .alert + } + else if (8 <= logLevelSlider.value && logLevelSlider.value < 9) { + logLevel = .emergency + } else { logLevel = .none } diff --git a/DemoApps/iOSDemo/watchOSDemo Extension/InterfaceController.swift b/DemoApps/iOSDemo/watchOSDemo Extension/InterfaceController.swift index c7282b8a..fd16c995 100644 --- a/DemoApps/iOSDemo/watchOSDemo Extension/InterfaceController.swift +++ b/DemoApps/iOSDemo/watchOSDemo Extension/InterfaceController.swift @@ -57,6 +57,10 @@ class InterfaceController: WKInterfaceController { log.info("Info tapped on the Watch") } + @IBAction func noticeButtonTapped(_ sender: WKInterfaceButton) { + log.notice("Notice tapped on the Watch") + } + @IBAction func warningButtonTapped(_ sender: WKInterfaceButton) { log.warning("Warning tapped on the Watch") } @@ -68,4 +72,12 @@ class InterfaceController: WKInterfaceController { @IBAction func severeButtonTapped(_ sender: WKInterfaceButton) { log.severe("Severe tapped on the Watch") } + + @IBAction func alertButtonTapped(_ sender: WKInterfaceButton) { + log.alert("Alert tapped on the Watch") + } + + @IBAction func emergencyButtonTapped(_ sender: WKInterfaceButton) { + log.emergency("Emergency tapped on the Watch") + } } diff --git a/DemoApps/iOSDemo/watchOSDemo/Base.lproj/Interface.storyboard b/DemoApps/iOSDemo/watchOSDemo/Base.lproj/Interface.storyboard index 093db66e..ee474bcd 100644 --- a/DemoApps/iOSDemo/watchOSDemo/Base.lproj/Interface.storyboard +++ b/DemoApps/iOSDemo/watchOSDemo/Base.lproj/Interface.storyboard @@ -1,12 +1,10 @@ - - - - + + - - + + @@ -31,6 +29,11 @@ + + + diff --git a/DemoApps/macOSDemo/macOSDemo/AppDelegate.swift b/DemoApps/macOSDemo/macOSDemo/AppDelegate.swift index a60f274c..9e8aa472 100644 --- a/DemoApps/macOSDemo/macOSDemo/AppDelegate.swift +++ b/DemoApps/macOSDemo/macOSDemo/AppDelegate.swift @@ -126,6 +126,14 @@ class AppDelegate: NSObject, NSApplicationDelegate { } } + @IBAction func noticeButtonTouchUpInside(_ sender: AnyObject) { + log.notice("Notice button tapped") + log.notice { + // add expensive code required only for logging, then return an optional String + return "Executed notice code block" // or nil + } + } + @IBAction func warningButtonTouchUpInside(_ sender: AnyObject) { log.warning("Warning button tapped") log.warning { @@ -150,14 +158,32 @@ class AppDelegate: NSObject, NSApplicationDelegate { } } - @IBAction func rotateLogFileButtonTouchUpInside(_ sender: AnyObject) { - if let fileDestination = log.destination(withIdentifier: "advancedLogger.fileDestination") as? FileDestination { + @IBAction func alertButtonTouchUpInside(_ sender: AnyObject) { + log.alert("Alert button tapped") + log.alert { + // add expensive code required only for logging, then return an optional String + return "Executed alert code block" // or nil + } + } - let dateHash: String = dateHashFormatter.string(from: Date()) - let archiveFilePath: String = ("~/Desktop/XCGLogger_Log_\(dateHash).txt" as NSString).expandingTildeInPath + @IBAction func emergencyButtonTouchUpInside(_ sender: AnyObject) { + log.emergency("Emergency button tapped") + log.emergency { + // add expensive code required only for logging, then return an optional String + return "Executed emergency code block" // or nil + } + } - fileDestination.rotateFile(to: archiveFilePath) + @IBAction func rotateLogFileButtonTouchUpInside(_ sender: AnyObject) { + guard let fileDestination = log.destination(withIdentifier: "advancedLogger.fileDestination") as? FileDestination else { + log.error("File destination not found, unable to rotate the log") + return } + + let dateHash: String = dateHashFormatter.string(from: Date()) + let archiveFilePath: String = ("~/Desktop/XCGLogger_Log_\(dateHash).txt" as NSString).expandingTildeInPath + + fileDestination.rotateFile(to: archiveFilePath) } @IBAction func logLevelSliderValueChanged(_ sender: AnyObject) { @@ -173,14 +199,23 @@ class AppDelegate: NSObject, NSApplicationDelegate { logLevel = .info } else if (3 <= logLevelSlider.floatValue && logLevelSlider.floatValue < 4) { - logLevel = .warning + logLevel = .notice } else if (4 <= logLevelSlider.floatValue && logLevelSlider.floatValue < 5) { - logLevel = .error + logLevel = .warning } else if (5 <= logLevelSlider.floatValue && logLevelSlider.floatValue < 6) { + logLevel = .error + } + else if (6 <= logLevelSlider.floatValue && logLevelSlider.floatValue < 7) { logLevel = .severe } + else if (7 <= logLevelSlider.floatValue && logLevelSlider.floatValue < 8) { + logLevel = .alert + } + else if (8 <= logLevelSlider.floatValue && logLevelSlider.floatValue < 9) { + logLevel = .emergency + } else { logLevel = .none } diff --git a/DemoApps/macOSDemo/macOSDemo/Base.lproj/MainMenu.xib b/DemoApps/macOSDemo/macOSDemo/Base.lproj/MainMenu.xib index 16aafb17..ebd46c67 100644 --- a/DemoApps/macOSDemo/macOSDemo/Base.lproj/MainMenu.xib +++ b/DemoApps/macOSDemo/macOSDemo/Base.lproj/MainMenu.xib @@ -1,7 +1,8 @@ - + - + + @@ -94,18 +95,19 @@ + - - + + - + - - + + @@ -115,8 +117,8 @@ - - + + @@ -126,8 +128,8 @@ - - + + @@ -138,17 +140,17 @@ - + - + + - + + @@ -250,6 +278,19 @@ + @@ -257,29 +298,38 @@ - + + + + + - + + + + + + @@ -290,7 +340,7 @@ - + diff --git a/DemoApps/tvOSDemo/tvOSDemo/Base.lproj/Main.storyboard b/DemoApps/tvOSDemo/tvOSDemo/Base.lproj/Main.storyboard index 296f61d8..7ae227ff 100644 --- a/DemoApps/tvOSDemo/tvOSDemo/Base.lproj/Main.storyboard +++ b/DemoApps/tvOSDemo/tvOSDemo/Base.lproj/Main.storyboard @@ -1,7 +1,11 @@ - - + + + - + + + + @@ -16,70 +20,90 @@ - - + + - - - + - + + - - - - - - + - + @@ -88,7 +112,7 @@ - + diff --git a/DemoApps/tvOSDemo/tvOSDemo/ViewController.swift b/DemoApps/tvOSDemo/tvOSDemo/ViewController.swift index 1e58b6bf..9e8925bd 100644 --- a/DemoApps/tvOSDemo/tvOSDemo/ViewController.swift +++ b/DemoApps/tvOSDemo/tvOSDemo/ViewController.swift @@ -33,6 +33,10 @@ class ViewController: UIViewController { log.info("Info tapped on the TV") } + @IBAction func noticeButtonTapped(_ sender: UIButton) { + log.notice("Notice tapped on the TV") + } + @IBAction func warningButtonTapped(_ sender: UIButton) { log.warning("Warning tapped on the TV") } @@ -44,4 +48,12 @@ class ViewController: UIViewController { @IBAction func severeButtonTapped(_ sender: UIButton) { log.severe("Severe tapped on the TV") } + + @IBAction func alertButtonTapped(_ sender: UIButton) { + log.alert("Alert tapped on the TV") + } + + @IBAction func emergencyButtonTapped(_ sender: UIButton) { + log.emergency("Emergency tapped on the TV") + } } From bdad85c61705d56d155d559ccf29e3e1d81748e8 Mon Sep 17 00:00:00 2001 From: Dave Wood Date: Tue, 4 Feb 2020 06:23:08 -0500 Subject: [PATCH 3/6] Xcode 11.3.1 project updates --- .../macOSDemo.xcodeproj/project.pbxproj | 5 ++-- .../xcshareddata/xcschemes/macOSDemo.xcscheme | 24 ++++++++----------- .../ObjcExceptionBridging (iOS).xcscheme | 6 +---- .../ObjcExceptionBridging (macOS).xcscheme | 6 +---- .../ObjcExceptionBridging (tvOS).xcscheme | 6 +---- .../ObjcExceptionBridging (watchOS).xcscheme | 6 +---- .../xcschemes/XCGLogger (iOS).xcscheme | 24 ++++++++----------- .../xcschemes/XCGLogger (macOS).xcscheme | 24 ++++++++----------- .../xcschemes/XCGLogger (tvOS).xcscheme | 24 ++++++++----------- .../xcschemes/XCGLogger (watchOS).xcscheme | 10 +++----- 10 files changed, 49 insertions(+), 86 deletions(-) diff --git a/DemoApps/macOSDemo/macOSDemo.xcodeproj/project.pbxproj b/DemoApps/macOSDemo/macOSDemo.xcodeproj/project.pbxproj index 48fd89c0..ba9e4a16 100644 --- a/DemoApps/macOSDemo/macOSDemo.xcodeproj/project.pbxproj +++ b/DemoApps/macOSDemo/macOSDemo.xcodeproj/project.pbxproj @@ -282,7 +282,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1130; ORGANIZATIONNAME = "Cerebral Gardens"; TargetAttributes = { 555FFCAC19D77B1800F62246 = { @@ -298,10 +298,9 @@ }; buildConfigurationList = 555FFCA819D77B1800F62246 /* Build configuration list for PBXProject "macOSDemo" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - English, en, Base, ); diff --git a/DemoApps/macOSDemo/macOSDemo.xcodeproj/xcshareddata/xcschemes/macOSDemo.xcscheme b/DemoApps/macOSDemo/macOSDemo.xcodeproj/xcshareddata/xcschemes/macOSDemo.xcscheme index 807e06b5..007929fa 100644 --- a/DemoApps/macOSDemo/macOSDemo.xcodeproj/xcshareddata/xcschemes/macOSDemo.xcscheme +++ b/DemoApps/macOSDemo/macOSDemo.xcodeproj/xcshareddata/xcschemes/macOSDemo.xcscheme @@ -1,6 +1,6 @@ + + + + @@ -53,17 +62,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + @@ -53,17 +62,6 @@ - - - - - - - - + + + + @@ -39,17 +48,6 @@ - - - - - - - - + + + + @@ -53,17 +62,6 @@ - - - - - - - - - - - - + + - - Date: Tue, 4 Feb 2020 06:35:41 -0500 Subject: [PATCH 4/6] Version bump 7.0.1 --- CHANGELOG.md | 1 + DemoApps/iOSDemo/iOSDemo.xcodeproj/project.pbxproj | 4 ++-- .../macOSDemo/macOSDemo.xcodeproj/project.pbxproj | 4 ++-- .../tvOSDemo/tvOSDemo.xcodeproj/project.pbxproj | 4 ++-- ObjcExceptionBridging.podspec | 4 ++-- README.md | 14 +++++++------- Sources/XCGLogger/XCGLogger.swift | 2 +- XCGLogger.podspec | 2 +- XCGLogger.xcodeproj/project.pbxproj | 4 ++-- 9 files changed, 20 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3eaf4bac..0584600a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Change Log +* **Version 7.0.1**: *(2020/02/04)* - Updated for Xcode 11.3.1, adds in missing convenience methods for notice, alert, and emergency (thanks @hk05) * **Version 7.0.0**: *(2019/03/26)* - Updated for Xcode 10.2/Swift 5.0, adds additional log levels: notice, alert, and emergency * **Version 6.1.0**: *(2018/09/16)* - Fix for Xcode 10.0 warnings/Swift 4.2, other minor tweaks * **Version 6.0.4**: *(2018/06/11)* - Fix for Xcode 9.3 warnings/Swift 4.1 (thanks @ijaureguialzo), and other fixes diff --git a/DemoApps/iOSDemo/iOSDemo.xcodeproj/project.pbxproj b/DemoApps/iOSDemo/iOSDemo.xcodeproj/project.pbxproj index 3d73ba81..7ff7f3f5 100644 --- a/DemoApps/iOSDemo/iOSDemo.xcodeproj/project.pbxproj +++ b/DemoApps/iOSDemo/iOSDemo.xcodeproj/project.pbxproj @@ -712,7 +712,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 7.0.0; + CURRENT_PROJECT_VERSION = 7.0.1; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -761,7 +761,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 7.0.0; + CURRENT_PROJECT_VERSION = 7.0.1; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; diff --git a/DemoApps/macOSDemo/macOSDemo.xcodeproj/project.pbxproj b/DemoApps/macOSDemo/macOSDemo.xcodeproj/project.pbxproj index ba9e4a16..ea7e064e 100644 --- a/DemoApps/macOSDemo/macOSDemo.xcodeproj/project.pbxproj +++ b/DemoApps/macOSDemo/macOSDemo.xcodeproj/project.pbxproj @@ -496,7 +496,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 7.0.0; + CURRENT_PROJECT_VERSION = 7.0.1; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -553,7 +553,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 7.0.0; + CURRENT_PROJECT_VERSION = 7.0.1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; diff --git a/DemoApps/tvOSDemo/tvOSDemo.xcodeproj/project.pbxproj b/DemoApps/tvOSDemo/tvOSDemo.xcodeproj/project.pbxproj index 1cd43f36..b01bdbf8 100644 --- a/DemoApps/tvOSDemo/tvOSDemo.xcodeproj/project.pbxproj +++ b/DemoApps/tvOSDemo/tvOSDemo.xcodeproj/project.pbxproj @@ -484,7 +484,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 7.0.0; + CURRENT_PROJECT_VERSION = 7.0.1; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -541,7 +541,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 7.0.0; + CURRENT_PROJECT_VERSION = 7.0.1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; diff --git a/ObjcExceptionBridging.podspec b/ObjcExceptionBridging.podspec index 8a788dff..7f23f8b3 100644 --- a/ObjcExceptionBridging.podspec +++ b/ObjcExceptionBridging.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |spec| spec.name = 'ObjcExceptionBridging' - spec.version = '7.0.0' + spec.version = '7.0.1' spec.summary = 'A bridge to Objective-C exception handling, for use in Swift projects.' spec.description = <<-DESC @@ -16,7 +16,7 @@ Pod::Spec.new do |spec| spec.platforms = { :ios => '8.0', :watchos => '2.0', :tvos => '9.0' } spec.requires_arc = true - spec.source = { :git => 'https://github.com/DaveWoodCom/XCGLogger.git', :tag => '7.0.0' } + spec.source = { :git => 'https://github.com/DaveWoodCom/XCGLogger.git', :tag => '7.0.1' } spec.ios.deployment_target = '8.0' spec.osx.deployment_target = '10.10' diff --git a/README.md b/README.md index ef38e96a..8511b6fa 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ in your repository folder. Add the following line to your `Cartfile`. -```github "DaveWoodCom/XCGLogger" ~> 7.0.0``` +```github "DaveWoodCom/XCGLogger" ~> 7.0.1``` Then run `carthage update --no-use-binaries` or just `carthage update`. For details of the installation and usage of Carthage, visit [its project page][carthage]. @@ -71,12 +71,12 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' use_frameworks! -pod 'XCGLogger', '~> 7.0.0' +pod 'XCGLogger', '~> 7.0.1' ``` Specifying the pod `XCGLogger` on its own will include the core framework. We're starting to add subspecs to allow you to include optional components as well: -`pod 'XCGLogger/UserInfoHelpers', '~> 7.0.0'`: Include some experimental code to help deal with using UserInfo dictionaries to tag log messages. +`pod 'XCGLogger/UserInfoHelpers', '~> 7.0.1'`: Include some experimental code to help deal with using UserInfo dictionaries to tag log messages. Then run `pod install`. For details of the installation and usage of CocoaPods, visit [its official web site][cocoapods]. @@ -118,7 +118,7 @@ Add the following entry to your package's dependencies: ### Backwards Compatibility Use: -* XCGLogger version [7.0.0][xcglogger-7.0.0] for Swift 5.0 +* XCGLogger version [7.0.1][xcglogger-7.0.1] for Swift 5.0 * XCGLogger version [6.1.0][xcglogger-6.1.0] for Swift 4.2 * XCGLogger version [6.0.4][xcglogger-6.0.4] for Swift 4.1 * XCGLogger version [6.0.2][xcglogger-6.0.2] for Swift 4.0 @@ -568,9 +568,9 @@ The change log is now in its own file: [CHANGELOG.md](CHANGELOG.md) [badge-platforms]: https://img.shields.io/badge/Platforms-macOS%20%7C%20iOS%20%7C%20tvOS%20%7C%20watchOS-lightgray.svg?style=flat [badge-license]: https://img.shields.io/badge/License-MIT-lightgrey.svg?style=flat [badge-travis]: https://img.shields.io/travis/DaveWoodCom/XCGLogger/master.svg?style=flat -[badge-swiftpm]: https://img.shields.io/badge/Swift_Package_Manager-v7.0.0-64a6dd.svg?style=flat +[badge-swiftpm]: https://img.shields.io/badge/Swift_Package_Manager-v7.0.1-64a6dd.svg?style=flat [badge-cocoapods]: https://img.shields.io/cocoapods/v/XCGLogger.svg?style=flat -[badge-carthage]: https://img.shields.io/badge/Carthage-v7.0.0-64a6dd.svg?style=flat +[badge-carthage]: https://img.shields.io/badge/Carthage-v7.0.1-64a6dd.svg?style=flat [badge-sponsors]: https://img.shields.io/badge/Sponsors-Cerebral%20Gardens-orange.svg?style=flat [badge-mastodon]: https://img.shields.io/badge/Mastodon-DaveWoodX-606A84.svg?style=flat @@ -584,7 +584,7 @@ The change log is now in its own file: [CHANGELOG.md](CHANGELOG.md) [Firelog]: http://jogabo.github.io/firelog/ [Firebase]: https://www.firebase.com/ -[xcglogger-7.0.0]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/7.0.0 +[xcglogger-7.0.1]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/7.0.1 [xcglogger-6.1.0]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/6.1.0 [xcglogger-6.0.4]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/6.0.4 [xcglogger-6.0.2]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/6.0.2 diff --git a/Sources/XCGLogger/XCGLogger.swift b/Sources/XCGLogger/XCGLogger.swift index fdd2c114..b694b76b 100644 --- a/Sources/XCGLogger/XCGLogger.swift +++ b/Sources/XCGLogger/XCGLogger.swift @@ -46,7 +46,7 @@ open class XCGLogger: CustomDebugStringConvertible { public static let userInfoKeyInternal = "\(baseIdentifier).internal" /// Library version number - public static let versionString = "7.0.0" + public static let versionString = "7.0.1" /// Internal userInfo internal static let internalUserInfo: [String: Any] = [XCGLogger.Constants.userInfoKeyInternal: true] diff --git a/XCGLogger.podspec b/XCGLogger.podspec index 043744d2..f76f1340 100644 --- a/XCGLogger.podspec +++ b/XCGLogger.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |spec| spec.name = 'XCGLogger' - spec.version = '7.0.0' + spec.version = '7.0.1' spec.summary = 'A debug log module for use in Swift projects.' spec.description = <<-DESC diff --git a/XCGLogger.xcodeproj/project.pbxproj b/XCGLogger.xcodeproj/project.pbxproj index 62dec380..23682fde 100644 --- a/XCGLogger.xcodeproj/project.pbxproj +++ b/XCGLogger.xcodeproj/project.pbxproj @@ -1430,7 +1430,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 7.0.0; + CURRENT_PROJECT_VERSION = 7.0.1; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -1493,7 +1493,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 7.0.0; + CURRENT_PROJECT_VERSION = 7.0.1; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; From 0d65890fd84c79baa64a914728302b70dcecf71c Mon Sep 17 00:00:00 2001 From: Bill Patterson Date: Mon, 9 Nov 2020 08:30:38 -0700 Subject: [PATCH 5/6] Add documentation Add documentation to explain how AutoRotatingFileDestination works, to help users understand the imporance of several configuration parameters. --- .../AutoRotatingFileDestination.swift | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/Sources/XCGLogger/Destinations/AutoRotatingFileDestination.swift b/Sources/XCGLogger/Destinations/AutoRotatingFileDestination.swift index f37bfde3..7f1d43ee 100644 --- a/Sources/XCGLogger/Destinations/AutoRotatingFileDestination.swift +++ b/Sources/XCGLogger/Destinations/AutoRotatingFileDestination.swift @@ -10,7 +10,15 @@ import Foundation // MARK: - AutoRotatingFileDestination -/// A destination that outputs log details to files in a log folder, with auto-rotate options (by size or by time) +/// A destination that outputs log details to files in a log folder, with auto-rotate options (by size or by time). +/// +/// The number of allowed files is controlled by targetMaxLogFiles. +/// +/// The maximum size per file is controlled by setting maxFileSize. Archived files will be auto-deleted, oldest first, to try to keep file count from exceeding this number (though count may exceed the maximum temporarily). +/// +/// Rotation triggering is controlled by the values set for maxFileSize and maxTimeInterval (or defaults, if you do not specify a value). Either can trigger rotation as they are applied independently. Note that both have default values, so omitting values is not equal to "no limit"! +/// +/// If you use multiple AutoRotatingFileDestinations: file sets (current + archived files) are grouped by the .identifier you specify, not simply by filename patterns. If you omit the identifier and use the default of "" (empty string), then ALL files in the directory will be considered part of the same set, even when they are being created by multiple AutoRotatingFileDestinations. This may cause unexpected behavior when choosing the "oldest file" to delete, as ALL files will be considered as a group. To avoid this, either always specify a unique .identifier per destination, or point each AutoRotatingFileDestinations at its own directory. open class AutoRotatingFileDestination: FileDestination { // MARK: - Constants public static let autoRotatingFileDefaultMaxFileSize: UInt64 = 1_048_576 @@ -103,6 +111,19 @@ open class AutoRotatingFileDestination: FileDestination { } // MARK: - Life Cycle + /// Create an instance implemented as a set of multiple linked files that will be managed as a group based on identifier. + /// + /// - Parameters: + /// - owner: The log level of this logger, any logs received at this level or higher will be output to the destinations. **Default:** none + /// - writeToFile: FileURL or path (as String) to the base (active) file, which will be rotated out to archived file(s) based on other settings. + /// - identifier: Arbitrary value to "tag" base file + rotated archive files as belonging to the same group; added as a custom attribute on files for later examination when determining files to auto-delete as part of rotation. + /// - shouldAppend: Overwrite existing file (false), or continue existing file if any (true). **Default:** false + /// - appendMarker: Text to add to log file when reconnecting to an existing file (ignored if shouldAppend is false). + /// - attributes: File attributes to use when creating file. **Default:** nil + /// - maxFileSize: Desired maximum size of active file before rotating to archive and starting new active file. **Default:** autoRotatingFileDefaultMaxFileSize + /// - maxTimeInterval: Desired maximum size of active file before rotating to archive and starting new active file. Note that a "good" value for this parameter is highly application-dependent, based on logging volume! **Default:** autoRotatingFileDefaultMaxTimeInterval + /// - archiveSuffixDateFormatter: Formatter for creating the suffix added to base log file name for log rotation to archive files. **Default:** nil + /// - targetMaxLogFiles: Maximum number of files to keep, couting active + archived. When rotating, the oldest archived files will be deleted until remaining count is at or under this number. **Default:** 10 public init(owner: XCGLogger? = nil, writeToFile: Any, identifier: String = "", shouldAppend: Bool = false, appendMarker: String? = "-- ** ** ** --", attributes: [FileAttributeKey: Any]? = nil, maxFileSize: UInt64 = autoRotatingFileDefaultMaxFileSize, maxTimeInterval: TimeInterval = autoRotatingFileDefaultMaxTimeInterval, archiveSuffixDateFormatter: DateFormatter? = nil, targetMaxLogFiles: UInt8 = 10) { super.init(owner: owner, writeToFile: writeToFile, identifier: identifier, shouldAppend: true, appendMarker: shouldAppend ? appendMarker : nil, attributes: attributes) From d64a6c2f6ebe72becdc656ba6e494f49d3bbb40c Mon Sep 17 00:00:00 2001 From: Bill Patterson Date: Mon, 9 Nov 2020 08:36:13 -0700 Subject: [PATCH 6/6] Correct documentation from last update. Move text to describe the right parameter, as it was placed on the wrong one. --- .../Destinations/AutoRotatingFileDestination.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/XCGLogger/Destinations/AutoRotatingFileDestination.swift b/Sources/XCGLogger/Destinations/AutoRotatingFileDestination.swift index 7f1d43ee..085363c1 100644 --- a/Sources/XCGLogger/Destinations/AutoRotatingFileDestination.swift +++ b/Sources/XCGLogger/Destinations/AutoRotatingFileDestination.swift @@ -12,11 +12,11 @@ import Foundation // MARK: - AutoRotatingFileDestination /// A destination that outputs log details to files in a log folder, with auto-rotate options (by size or by time). /// -/// The number of allowed files is controlled by targetMaxLogFiles. +/// The number of allowed files is controlled by targetMaxLogFiles. Archived files will be auto-deleted, oldest first, to try to keep file count from exceeding this number (though count may exceed the maximum temporarily). /// -/// The maximum size per file is controlled by setting maxFileSize. Archived files will be auto-deleted, oldest first, to try to keep file count from exceeding this number (though count may exceed the maximum temporarily). +/// The maximum size per file is controlled by setting maxFileSize. The active file will be rotated to archive at _approximately_ this file size. /// -/// Rotation triggering is controlled by the values set for maxFileSize and maxTimeInterval (or defaults, if you do not specify a value). Either can trigger rotation as they are applied independently. Note that both have default values, so omitting values is not equal to "no limit"! +/// Rotation triggering is controlled by the values set for maxFileSize and maxTimeInterval, and either can trigger rotation as they are applied independently. Note that both have default values, so omitting values is not equal to "no limit"! /// /// If you use multiple AutoRotatingFileDestinations: file sets (current + archived files) are grouped by the .identifier you specify, not simply by filename patterns. If you omit the identifier and use the default of "" (empty string), then ALL files in the directory will be considered part of the same set, even when they are being created by multiple AutoRotatingFileDestinations. This may cause unexpected behavior when choosing the "oldest file" to delete, as ALL files will be considered as a group. To avoid this, either always specify a unique .identifier per destination, or point each AutoRotatingFileDestinations at its own directory. open class AutoRotatingFileDestination: FileDestination { @@ -120,7 +120,7 @@ open class AutoRotatingFileDestination: FileDestination { /// - shouldAppend: Overwrite existing file (false), or continue existing file if any (true). **Default:** false /// - appendMarker: Text to add to log file when reconnecting to an existing file (ignored if shouldAppend is false). /// - attributes: File attributes to use when creating file. **Default:** nil - /// - maxFileSize: Desired maximum size of active file before rotating to archive and starting new active file. **Default:** autoRotatingFileDefaultMaxFileSize + /// - maxFileSize: Desired maximum size (in bytes) of active file before rotating to archive and starting new active file. **Default:** autoRotatingFileDefaultMaxFileSize /// - maxTimeInterval: Desired maximum size of active file before rotating to archive and starting new active file. Note that a "good" value for this parameter is highly application-dependent, based on logging volume! **Default:** autoRotatingFileDefaultMaxTimeInterval /// - archiveSuffixDateFormatter: Formatter for creating the suffix added to base log file name for log rotation to archive files. **Default:** nil /// - targetMaxLogFiles: Maximum number of files to keep, couting active + archived. When rotating, the oldest archived files will be deleted until remaining count is at or under this number. **Default:** 10