From 733be701b45d75191582c86583c0da291fe5b5a5 Mon Sep 17 00:00:00 2001 From: Dave Wood Date: Tue, 4 Feb 2020 06:21:00 -0500 Subject: [PATCH 1/8] 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/8] 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/8] 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/8] 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 b27b1b05ce7a086b0e32a03b8d0a7bc7c1cb880a Mon Sep 17 00:00:00 2001 From: Dean Harel Date: Tue, 14 Sep 2021 17:15:14 +0300 Subject: [PATCH 5/8] Allow configuration of prefix; for both internal and external use cases --- .../contents.xcworkspacedata | 7 +++ .../Destinations/BaseDestination.swift | 59 +++++++++++-------- .../Destinations/DestinationProtocol.swift | 6 ++ Tests/XCGLoggerTests/XCGLoggerTests.swift | 6 +- 4 files changed, 49 insertions(+), 29 deletions(-) create mode 100644 .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Sources/XCGLogger/Destinations/BaseDestination.swift b/Sources/XCGLogger/Destinations/BaseDestination.swift index 470d755e..58c49eeb 100644 --- a/Sources/XCGLogger/Destinations/BaseDestination.swift +++ b/Sources/XCGLogger/Destinations/BaseDestination.swift @@ -67,7 +67,7 @@ open class BaseDestination: DestinationProtocol, CustomDebugStringConvertible { self.owner = owner self.identifier = identifier } - + // MARK: - Methods to Process Log Details /// Process the log details. /// @@ -77,22 +77,27 @@ open class BaseDestination: DestinationProtocol, CustomDebugStringConvertible { /// - Returns: Nothing /// open func process(logDetails: LogDetails) { - guard let owner = owner else { return } - + guard let prefix = messagePrefix(from: logDetails) else { return } + output(logDetails: logDetails, message: "\(prefix)\(logDetails.message)") + } + + open func messagePrefix(from details: LogDetails) -> String? { + guard let owner = owner else { return nil } + var extendedDetails: String = "" - + if showDate { - extendedDetails += "\((owner.dateFormatter != nil) ? owner.dateFormatter!.string(from: logDetails.date) : logDetails.date.description) " + extendedDetails += "\((owner.dateFormatter != nil) ? owner.dateFormatter!.string(from: details.date) : details.date.description) " } - + if showLevel { - extendedDetails += "[\(levelDescriptions[logDetails.level] ?? owner.levelDescriptions[logDetails.level] ?? logDetails.level.description)] " + extendedDetails += "[\(levelDescriptions[details.level] ?? owner.levelDescriptions[details.level] ?? details.level.description)] " } - + if showLogIdentifier { extendedDetails += "[\(owner.identifier)] " } - + if showThreadName { if Thread.isMainThread { extendedDetails += "[main] " @@ -109,19 +114,19 @@ open class BaseDestination: DestinationProtocol, CustomDebugStringConvertible { } } } - + if showFileName { - extendedDetails += "[\((logDetails.fileName as NSString).lastPathComponent)\((showLineNumber ? ":" + String(logDetails.lineNumber) : ""))] " + extendedDetails += "[\((details.fileName as NSString).lastPathComponent)\((showLineNumber ? ":" + String(details.lineNumber) : ""))] " } else if showLineNumber { - extendedDetails += "[\(logDetails.lineNumber)] " + extendedDetails += "[\(details.lineNumber)] " } - + if showFunctionName { - extendedDetails += "\(logDetails.functionName) " + extendedDetails += "\(details.functionName) " } - - output(logDetails: logDetails, message: "\(extendedDetails)> \(logDetails.message)") + + return "\(extendedDetails)> " } /// Process the log details (internal use, same as process(logDetails:) but omits function/file/line info). @@ -132,23 +137,27 @@ open class BaseDestination: DestinationProtocol, CustomDebugStringConvertible { /// - Returns: Nothing /// open func processInternal(logDetails: LogDetails) { - guard let owner = owner else { return } - + guard let prefix = internalMessagePrefix(from: logDetails) else { return } + output(logDetails: logDetails, message: "\(prefix)\(logDetails.message)") + } + + open func internalMessagePrefix(from details: LogDetails) -> String? { + guard let owner = owner else { return nil } + var extendedDetails: String = "" - + if showDate { - extendedDetails += "\((owner.dateFormatter != nil) ? owner.dateFormatter!.string(from: logDetails.date) : logDetails.date.description) " + extendedDetails += "\((owner.dateFormatter != nil) ? owner.dateFormatter!.string(from: details.date) : details.date.description) " } - + if showLevel { - extendedDetails += "[\(logDetails.level)] " + extendedDetails += "[\(details.level)] " } - + if showLogIdentifier { extendedDetails += "[\(owner.identifier)] " } - - output(logDetails: logDetails, message: "\(extendedDetails)> \(logDetails.message)") + return "\(extendedDetails)> " } // MARK: - Misc methods diff --git a/Sources/XCGLogger/Destinations/DestinationProtocol.swift b/Sources/XCGLogger/Destinations/DestinationProtocol.swift index d10e761b..64d397cb 100644 --- a/Sources/XCGLogger/Destinations/DestinationProtocol.swift +++ b/Sources/XCGLogger/Destinations/DestinationProtocol.swift @@ -48,6 +48,12 @@ public protocol DestinationProtocol: CustomDebugStringConvertible { /// func processInternal(logDetails: LogDetails) + // TODO: *dean* add documentation + func internalMessagePrefix(from details: LogDetails) -> String? + + // TODO: *dean* add documentation + func messagePrefix(from details: LogDetails) -> String? + /// Check if the destination's log level is equal to or lower than the specified level. /// /// - Parameters: diff --git a/Tests/XCGLoggerTests/XCGLoggerTests.swift b/Tests/XCGLoggerTests/XCGLoggerTests.swift index 2041c6bb..6b2c49e0 100644 --- a/Tests/XCGLoggerTests/XCGLoggerTests.swift +++ b/Tests/XCGLoggerTests/XCGLoggerTests.swift @@ -454,7 +454,7 @@ class XCGLoggerTests: XCTestCase { let knownDate = Date(timeIntervalSince1970: 0) testDestination.add(expectedLogMessage: "[\(XCGLogger.Level.error)] [\(fileName)] \(#function) > \(knownDate)") XCTAssert(testDestination.remainingNumberOfExpectedLogMessages == 1, "Fail: Didn't correctly load all of the expected log messages") - log.error { return knownDate } + log.error({ return knownDate }) XCTAssert(testDestination.remainingNumberOfExpectedLogMessages == 0, "Fail: Didn't receive all expected log lines") XCTAssert(testDestination.numberOfUnexpectedLogMessages == 0, "Fail: Received an unexpected log line") @@ -926,9 +926,7 @@ class XCGLoggerTests: XCTestCase { let myConcurrentQueue = DispatchQueue(label: log.identifier + ".concurrentQueue", attributes: .concurrent) myConcurrentQueue.sync { DispatchQueue.concurrentPerform(iterations: linesToLog.count) { (index: Int) -> () in - log.debug { - return "\(linesToLog[index])" - } + log.debug({ return "\(linesToLog[index])" }) } } From b45ad47878bcbfbe678bdcce7bada75c28e3f7c5 Mon Sep 17 00:00:00 2001 From: Dean Harel Date: Tue, 14 Sep 2021 17:24:54 +0300 Subject: [PATCH 6/8] Add documentation --- Sources/XCGLogger/Destinations/DestinationProtocol.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Sources/XCGLogger/Destinations/DestinationProtocol.swift b/Sources/XCGLogger/Destinations/DestinationProtocol.swift index 64d397cb..e8cfc931 100644 --- a/Sources/XCGLogger/Destinations/DestinationProtocol.swift +++ b/Sources/XCGLogger/Destinations/DestinationProtocol.swift @@ -48,10 +48,12 @@ public protocol DestinationProtocol: CustomDebugStringConvertible { /// func processInternal(logDetails: LogDetails) - // TODO: *dean* add documentation + /// Returns a string to use when processing the log details (internal use, same as processLogDetails but omits function/file/line info) + /// - Parameter details: A string to use when processing the log details. func internalMessagePrefix(from details: LogDetails) -> String? - - // TODO: *dean* add documentation + + /// Returns a string to use when processing the log details. + /// - Parameter details: A string to use when processing the log details. func messagePrefix(from details: LogDetails) -> String? /// Check if the destination's log level is equal to or lower than the specified level. From 02d0bb1fd31309a830f06931444adee4b767b2f0 Mon Sep 17 00:00:00 2001 From: Dean Harel Date: Tue, 14 Sep 2021 17:43:49 +0300 Subject: [PATCH 7/8] Fix ambiguous use of logln --- Sources/XCGLogger/XCGLogger.swift | 42 ++++++------------------------- 1 file changed, 8 insertions(+), 34 deletions(-) diff --git a/Sources/XCGLogger/XCGLogger.swift b/Sources/XCGLogger/XCGLogger.swift index b694b76b..b43f00c4 100644 --- a/Sources/XCGLogger/XCGLogger.swift +++ b/Sources/XCGLogger/XCGLogger.swift @@ -275,22 +275,6 @@ open class XCGLogger: CustomDebugStringConvertible { self.default.logln(level, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) } - /// Log a message if the logger's log level is equal to or lower than the specified level. - /// - /// - Parameters: - /// - level: Specified log level **Default:** *Debug*. - /// - 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 logln(_ level: Level = .debug, functionName: String = #function, fileName: String = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { - self.default.logln(level, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) - } - /// Log a message if the logger's log level is equal to or lower than the specified level. /// /// - Parameters: @@ -320,27 +304,17 @@ open class XCGLogger: CustomDebugStringConvertible { /// - Returns: Nothing /// open func logln(_ level: Level = .debug, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { - logln(level, functionName: String(describing: functionName), fileName: String(describing: fileName), lineNumber: lineNumber, userInfo: userInfo, closure: closure) - } - - /// Log a message if the logger's log level is equal to or lower than the specified level. - /// - /// - Parameters: - /// - level: Specified log level **Default:** *Debug*. - /// - 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 logln(_ level: Level = .debug, functionName: String = #function, fileName: String = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { let enabledDestinations = destinations.filter({$0.isEnabledFor(level: level)}) guard enabledDestinations.count > 0 else { return } guard let closureResult = closure() else { return } - - let logDetails: LogDetails = LogDetails(level: level, date: Date(), message: String(describing: closureResult), functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo) + + let logDetails = LogDetails(level: level, + date: Date(), + message: String(describing: closureResult), + functionName: "\(functionName)", + fileName: "\(fileName)", + lineNumber: lineNumber, + userInfo: userInfo) for destination in enabledDestinations { destination.process(logDetails: logDetails) } From 59512cc6854668d9b6d1f126f18ec9733014a5c4 Mon Sep 17 00:00:00 2001 From: Dean Harel Date: Sun, 19 Sep 2021 16:59:19 +0300 Subject: [PATCH 8/8] Update requirements --- .../Destinations/BaseDestination.swift | 37 ++++++++++-- .../Destinations/DestinationProtocol.swift | 60 +++++++++++++------ 2 files changed, 72 insertions(+), 25 deletions(-) diff --git a/Sources/XCGLogger/Destinations/BaseDestination.swift b/Sources/XCGLogger/Destinations/BaseDestination.swift index 58c49eeb..9d93221f 100644 --- a/Sources/XCGLogger/Destinations/BaseDestination.swift +++ b/Sources/XCGLogger/Destinations/BaseDestination.swift @@ -77,11 +77,27 @@ open class BaseDestination: DestinationProtocol, CustomDebugStringConvertible { /// - Returns: Nothing /// open func process(logDetails: LogDetails) { - guard let prefix = messagePrefix(from: logDetails) else { return } + guard + let prefix = messagePrefix(from: logDetails, + showDate: self.showDate, + showLevel: self.showLevel, + showLogIdentifier: self.showLogIdentifier, + showThreadName: self.showThreadName, + showFileName: self.showFileName, + showLineNumber: self.showLineNumber, + showFunctionName: self.showFunctionName) + else { return } output(logDetails: logDetails, message: "\(prefix)\(logDetails.message)") } - open func messagePrefix(from details: LogDetails) -> String? { + open func messagePrefix(from details: LogDetails, + showDate: Bool, + showLevel: Bool, + showLogIdentifier: Bool, + showThreadName: Bool, + showFileName: Bool, + showLineNumber: Bool, + showFunctionName: Bool) -> String? { guard let owner = owner else { return nil } var extendedDetails: String = "" @@ -126,7 +142,7 @@ open class BaseDestination: DestinationProtocol, CustomDebugStringConvertible { extendedDetails += "\(details.functionName) " } - return "\(extendedDetails)> " + return extendedDetails.isEmpty ? extendedDetails : "\(extendedDetails)> " } /// Process the log details (internal use, same as process(logDetails:) but omits function/file/line info). @@ -137,11 +153,19 @@ open class BaseDestination: DestinationProtocol, CustomDebugStringConvertible { /// - Returns: Nothing /// open func processInternal(logDetails: LogDetails) { - guard let prefix = internalMessagePrefix(from: logDetails) else { return } + guard + let prefix = internalMessagePrefix(from: logDetails, + showDate: self.showDate, + showLevel: self.showLevel, + showLogIdentifier: self.showLogIdentifier) + else { return } output(logDetails: logDetails, message: "\(prefix)\(logDetails.message)") } - open func internalMessagePrefix(from details: LogDetails) -> String? { + open func internalMessagePrefix(from details: LogDetails, + showDate: Bool, + showLevel: Bool, + showLogIdentifier: Bool) -> String? { guard let owner = owner else { return nil } var extendedDetails: String = "" @@ -157,7 +181,8 @@ open class BaseDestination: DestinationProtocol, CustomDebugStringConvertible { if showLogIdentifier { extendedDetails += "[\(owner.identifier)] " } - return "\(extendedDetails)> " + + return extendedDetails.isEmpty ? extendedDetails : "\(extendedDetails)> " } // MARK: - Misc methods diff --git a/Sources/XCGLogger/Destinations/DestinationProtocol.swift b/Sources/XCGLogger/Destinations/DestinationProtocol.swift index e8cfc931..939a6e94 100644 --- a/Sources/XCGLogger/Destinations/DestinationProtocol.swift +++ b/Sources/XCGLogger/Destinations/DestinationProtocol.swift @@ -13,22 +13,22 @@ public protocol DestinationProtocol: CustomDebugStringConvertible { // MARK: - Properties /// Logger that owns the destination object var owner: XCGLogger? {get set} - + /// Identifier for the destination (should be unique) var identifier: String {get set} - + /// Log level for this destination var outputLevel: XCGLogger.Level {get set} - + /// Flag whether or not we've logged the app details to this destination var haveLoggedAppDetails: Bool { get set } - + /// Array of log formatters to apply to messages before they're output var formatters: [LogFormatterProtocol]? { get set } - + /// Array of log filters to apply to messages before they're output var filters: [FilterProtocol]? { get set } - + // MARK: - Methods /// Process the log details. /// @@ -38,7 +38,7 @@ public protocol DestinationProtocol: CustomDebugStringConvertible { /// - Returns: Nothing /// func process(logDetails: LogDetails) - + /// Process the log details (internal use, same as processLogDetails but omits function/file/line info). /// /// - Parameters: @@ -47,14 +47,36 @@ public protocol DestinationProtocol: CustomDebugStringConvertible { /// - Returns: Nothing /// func processInternal(logDetails: LogDetails) - + /// Returns a string to use when processing the log details (internal use, same as processLogDetails but omits function/file/line info) - /// - Parameter details: A string to use when processing the log details. - func internalMessagePrefix(from details: LogDetails) -> String? + /// - Parameters: + /// - details: A string to use when processing the log details. + /// - showDate: Whether to show a formatted date string. + /// - showLevel: Whether to show the log level. + /// - showLogIdentifier: Whether to show a log identifier. + func internalMessagePrefix(from details: LogDetails, + showDate: Bool, + showLevel: Bool, + showLogIdentifier: Bool) -> String? /// Returns a string to use when processing the log details. - /// - Parameter details: A string to use when processing the log details. - func messagePrefix(from details: LogDetails) -> String? + /// - Parameters: + /// - details: A string to use when processing the log details. + /// - showDate: Whether to show a formatted date string. + /// - showLevel: Whether to show the log level. + /// - showLogIdentifier: Whether to show a log identifier. + /// - showThreadName: Whether to show the thread's name. + /// - showFileName: Whether to show the filename. + /// - showLineNumber: Whether to show the line number. + /// - showFunctionName: Whether to show the function name. + func messagePrefix(from details: LogDetails, + showDate: Bool, + showLevel: Bool, + showLogIdentifier: Bool, + showThreadName: Bool, + showFileName: Bool, + showLineNumber: Bool, + showFunctionName: Bool) -> String? /// Check if the destination's log level is equal to or lower than the specified level. /// @@ -66,7 +88,7 @@ public protocol DestinationProtocol: CustomDebugStringConvertible { /// - false: Log destination is at a higher log level. /// func isEnabledFor(level: XCGLogger.Level) -> Bool - + /// Apply filters to determine if the log message should be logged. /// /// - Parameters: @@ -78,7 +100,7 @@ public protocol DestinationProtocol: CustomDebugStringConvertible { /// - false: Keep this log message and continue processing. /// func shouldExclude(logDetails: inout LogDetails, message: inout String) -> Bool - + /// Apply formatters. /// /// - Parameters: @@ -91,7 +113,7 @@ public protocol DestinationProtocol: CustomDebugStringConvertible { } extension DestinationProtocol { - + /// Iterate over all of the log filters in this destination, or the logger if none set for the destination. /// /// - Parameters: @@ -104,16 +126,16 @@ extension DestinationProtocol { /// public func shouldExclude(logDetails: inout LogDetails, message: inout String) -> Bool { guard let filters = self.filters ?? self.owner?.filters, filters.count > 0 else { return false } - + for filter in filters { if filter.shouldExclude(logDetails: &logDetails, message: &message) { return true } } - + return false } - + /// Iterate over all of the log formatters in this destination, or the logger if none set for the destination. /// /// - Parameters: @@ -124,7 +146,7 @@ extension DestinationProtocol { /// public func applyFormatters(logDetails: inout LogDetails, message: inout String) { guard let formatters = self.formatters ?? self.owner?.formatters, formatters.count > 0 else { return } - + for formatter in formatters { formatter.format(logDetails: &logDetails, message: &message) }