From 475daeed6d194636563c9de6d71b4f4633af64b3 Mon Sep 17 00:00:00 2001 From: Matthew Lorentz Date: Thu, 21 Sep 2023 13:08:14 -0400 Subject: [PATCH 1/2] Use OSLog package to take advantage of Xcode 15 log formatting --- Package.resolved | 25 --------- Package.swift | 4 +- Sources/Delivery/Log.swift | 56 ++++++++++--------- Sources/Delivery/Models/LogProtocol.swift | 12 ++-- Sources/Domain/Services/LoggerService.swift | 10 ++-- .../Services/LoggerServiceAdapter.swift | 40 +++++++++---- 6 files changed, 71 insertions(+), 76 deletions(-) delete mode 100644 Package.resolved diff --git a/Package.resolved b/Package.resolved deleted file mode 100644 index 81656fc..0000000 --- a/Package.resolved +++ /dev/null @@ -1,25 +0,0 @@ -{ - "object": { - "pins": [ - { - "package": "CocoaLumberjack", - "repositoryURL": "https://github.com/CocoaLumberjack/CocoaLumberjack.git", - "state": { - "branch": null, - "revision": "e518eb6e362df327574ba5e04269cd6d29f40aec", - "version": "3.7.2" - } - }, - { - "package": "swift-log", - "repositoryURL": "https://github.com/apple/swift-log.git", - "state": { - "branch": null, - "revision": "5d66f7ba25daf4f94100e7022febf3c75e37a6c7", - "version": "1.4.2" - } - } - ] - }, - "version": 1 -} diff --git a/Package.swift b/Package.swift index 44a2721..c5c7748 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,7 @@ import PackageDescription let package = Package( name: "Logger", platforms: [ - .iOS(.v13) + .iOS(.v14) ], products: [ // Products define the executables and libraries a package produces, and make them visible to other packages. @@ -18,7 +18,7 @@ let package = Package( // Dependencies declare other packages that this package depends on. .package(name: "CocoaLumberjack", url: "https://github.com/CocoaLumberjack/CocoaLumberjack.git", - from: "3.7.0"), + from: "3.8.1"), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/Sources/Delivery/Log.swift b/Sources/Delivery/Log.swift index 08b8dda..c09f2b7 100644 --- a/Sources/Delivery/Log.swift +++ b/Sources/Delivery/Log.swift @@ -29,28 +29,28 @@ public class Log: LogProtocol { } @discardableResult - public func optional(_ error: Error?, _ detail: String? = nil) -> Bool { - service.optional(error, detail) + public func optional(_ error: Error?, _ detail: String? = nil, component: String = #file) -> Bool { + service.optional(error, detail, component: component) } - public func info(_ string: String) { - service.info(string) + public func info(_ string: String, component: String = #file) { + service.info(string, component: component) } - public func debug(_ string: String) { - service.debug(string) + public func debug(_ string: String, component: String = #file) { + service.debug(string, component: component) } - public func error(_ string: String) { - service.unexpected(string, nil) + public func error(_ string: String, component: String = #file) { + service.unexpected(string, nil, component: component) } - public func unexpected(_ reason: Reason, _ detail: String?) { - service.unexpected(reason.rawValue, detail) + public func unexpected(_ reason: Reason, _ detail: String?, component: String = #file) { + service.unexpected(reason.rawValue, detail, component: component) } - public func fatal(_ reason: Reason, _ detail: String?) { - service.fatal(reason.rawValue, detail) + public func fatal(_ reason: Reason, _ detail: String?, component: String = #file) { + service.fatal(reason.rawValue, detail, component: component) } } @@ -66,47 +66,51 @@ public extension Log { /// /// Convenience function that unwraps the error (if exists) and logs its description @discardableResult - static func optional(_ error: Error?, _ detail: String? = nil) -> Bool { - shared.optional(error, detail) + static func optional(_ error: Error?, _ detail: String? = nil, component: String = #file) -> Bool { + shared.optional(error, detail, component: component) } /// Log a INFO message - static func info(_ string: String) { - shared.info(string) + static func info(_ string: String, component: String = #file) { + shared.info(string, component: component) } /// Log a DEBUG message - static func debug(_ string: String) { - shared.debug(string) + static func debug(_ string: String, component: String = #file) { + shared.debug(string, component: component) } /// Log a ERROR message /// /// Convencience function that categorize common errors that the app can handle - static func unexpected(_ reason: Reason, _ detail: String?) { - shared.unexpected(reason, detail) + static func unexpected(_ reason: Reason, _ detail: String?, component: String = #file) { + shared.unexpected(reason, detail, component: component) } /// Log a FATAL message /// /// Convencience function that categorize common errors that the app cannot handle - static func fatal(_ reason: Reason, _ detail: String?) { - shared.fatal(reason, detail) + static func fatal(_ reason: Reason, _ detail: String?, component: String = #file) { + shared.fatal(reason, detail, component: component) } /// Log a ERROR message /// /// Convenience function that unwraps an error and a response from a network call - static func optional(_ error: Error?, from response: URLResponse?) { + static func optional(_ error: Error?, from response: URLResponse?, component: String = #file) { guard let error = error else { return } guard let response = response else { return } let path = response.url?.path ?? "unknown path" let detail = "\(path) \(error)" - shared.unexpected(.apiError, detail) + shared.unexpected(.apiError, detail, component: component) } /// Log a ERROR message - static func error(_ message: String) { - shared.error(message) + static func error(_ message: String, _ detail: String? = nil, component: String = #file) { + shared.error(message, component: component) + } + + static func error(_ error: Error, _ detail: String? = nil, component: String = #file) { + shared.optional(error, detail, component: component) } } diff --git a/Sources/Delivery/Models/LogProtocol.swift b/Sources/Delivery/Models/LogProtocol.swift index 3a68ebe..8ce9b1a 100644 --- a/Sources/Delivery/Models/LogProtocol.swift +++ b/Sources/Delivery/Models/LogProtocol.swift @@ -17,24 +17,24 @@ public protocol LogProtocol { /// /// Convenience function that unwraps the error (if exists) and logs its description @discardableResult - func optional(_ error: Error?, _ detail: String?) -> Bool + func optional(_ error: Error?, _ detail: String?, component: String) -> Bool /// Log a INFO message - func info(_ string: String) + func info(_ string: String, component: String) /// Log a DEBUG message - func debug(_ string: String) + func debug(_ string: String, component: String) /// Log a ERROR message - func error(_ string: String) + func error(_ string: String, component: String) /// Log a ERROR message /// /// Convencience function that categorize common errors that the app can handle - func unexpected(_ reason: Reason, _ detail: String?) + func unexpected(_ reason: Reason, _ detail: String?, component: String) /// Log a FATAL message /// /// Convencience function that categorize common errors that the app cannot handle - func fatal(_ reason: Reason, _ detail: String?) + func fatal(_ reason: Reason, _ detail: String?, component: String) } diff --git a/Sources/Domain/Services/LoggerService.swift b/Sources/Domain/Services/LoggerService.swift index 1415951..640f697 100644 --- a/Sources/Domain/Services/LoggerService.swift +++ b/Sources/Domain/Services/LoggerService.swift @@ -11,13 +11,13 @@ protocol LoggerService { var fileUrls: [URL] { get } - func debug(_ string: String) + func debug(_ string: String, component: String) - func info(_ string: String) + func info(_ string: String, component: String) - func optional(_ error: Error?, _ detail: String?) -> Bool + func optional(_ error: Error?, _ detail: String?, component: String) -> Bool - func unexpected(_ reason: String, _ detail: String?) + func unexpected(_ reason: String, _ detail: String?, component: String) - func fatal(_ reason: String, _ detail: String?) + func fatal(_ reason: String, _ detail: String?, component: String) } diff --git a/Sources/Domain/Services/LoggerServiceAdapter.swift b/Sources/Domain/Services/LoggerServiceAdapter.swift index 35cc114..80bdc33 100644 --- a/Sources/Domain/Services/LoggerServiceAdapter.swift +++ b/Sources/Domain/Services/LoggerServiceAdapter.swift @@ -6,15 +6,16 @@ // import Foundation -import os.log +import OSLog -/// The LoggerServiceAdapter class can be used to output logs to files in the device's filesystem +/// The LoggerServiceAdapter class can be used componenetoutput logs to files in the device's filesystem /// and to the Console (in real-time) when debugging /// /// It implements LoggerService so it is meant to be used by Log as a plug-in that actually outputs to logs somewhere. class LoggerServiceAdapter: LoggerService { var fileLoggerService: FileLoggerService + var loggers = [String: Logger]() init(fileLoggerService: FileLoggerService) { self.fileLoggerService = fileLoggerService @@ -24,37 +25,52 @@ class LoggerServiceAdapter: LoggerService { fileLoggerService.fileUrls } - func debug(_ string: String) { + func debug(_ string: String, component: String) { let message = "LOG:DEBUG: \(string)" fileLoggerService.debug(message) - os_log("%@", type: OSLogType.debug, message) + let osLogger = logger(for: component) + osLogger.debug("\(string)") } - func info(_ string: String) { + func info(_ string: String, component: String) { let message = "LOG:INFO: \(string)" - os_log("%@", type: OSLogType.info, message) fileLoggerService.info(message) + let osLogger = logger(for: component) + osLogger.info("\(string)") } - func optional(_ error: Error?, _ detail: String?) -> Bool { + func optional(_ error: Error?, _ detail: String?, component: String) -> Bool { guard let error = error else { return false } let message = "LOG:ERROR:\(detail ?? "") \(error)" - os_log("%@", type: OSLogType.error, message) fileLoggerService.error(message) + let osLogger = logger(for: component) + osLogger.error("\(detail ?? "") \(error)") return true } - func unexpected(_ reason: String, _ detail: String?) { + func unexpected(_ reason: String, _ detail: String?, component: String) { let message = "LOG:UNEXPECTED:\(reason) \(detail ?? "")" - os_log("%@", type: OSLogType.error, message) fileLoggerService.error(message) + let osLogger = logger(for: component) + osLogger.error("\(reason) \(detail ?? "")") } - func fatal(_ reason: String, _ detail: String?) { + func fatal(_ reason: String, _ detail: String?, component: String) { let message = "LOG:FATAL:\(reason) \(detail ?? "")" - os_log("%@", type: OSLogType.fault, message) fileLoggerService.error(message) + let osLogger = logger(for: component) + osLogger.error("\(reason) \(detail ?? "")") + } + + private func logger(for component: String) -> Logger { + if let logger = loggers[component] { + return logger + } else { + let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: component) + loggers[component] = logger + return logger + } } } From 2900bde83c173505616d1cb84fb7a98ab106e315 Mon Sep 17 00:00:00 2001 From: Matthew Lorentz Date: Thu, 21 Sep 2023 13:15:10 -0400 Subject: [PATCH 2/2] Rename component parameters to sourceFile --- Sources/Delivery/Log.swift | 56 +++++++++---------- Sources/Delivery/Models/LogProtocol.swift | 12 ++-- Sources/Domain/Services/LoggerService.swift | 10 ++-- .../Services/LoggerServiceAdapter.swift | 29 +++++----- 4 files changed, 54 insertions(+), 53 deletions(-) diff --git a/Sources/Delivery/Log.swift b/Sources/Delivery/Log.swift index c09f2b7..aa31791 100644 --- a/Sources/Delivery/Log.swift +++ b/Sources/Delivery/Log.swift @@ -29,28 +29,28 @@ public class Log: LogProtocol { } @discardableResult - public func optional(_ error: Error?, _ detail: String? = nil, component: String = #file) -> Bool { - service.optional(error, detail, component: component) + public func optional(_ error: Error?, _ detail: String? = nil, sourceFile: String = #file) -> Bool { + service.optional(error, detail, sourceFile: sourceFile) } - public func info(_ string: String, component: String = #file) { - service.info(string, component: component) + public func info(_ string: String, sourceFile: String = #file) { + service.info(string, sourceFile: sourceFile) } - public func debug(_ string: String, component: String = #file) { - service.debug(string, component: component) + public func debug(_ string: String, sourceFile: String = #file) { + service.debug(string, sourceFile: sourceFile) } - public func error(_ string: String, component: String = #file) { - service.unexpected(string, nil, component: component) + public func error(_ string: String, sourceFile: String = #file) { + service.unexpected(string, nil, sourceFile: sourceFile) } - public func unexpected(_ reason: Reason, _ detail: String?, component: String = #file) { - service.unexpected(reason.rawValue, detail, component: component) + public func unexpected(_ reason: Reason, _ detail: String?, sourceFile: String = #file) { + service.unexpected(reason.rawValue, detail, sourceFile: sourceFile) } - public func fatal(_ reason: Reason, _ detail: String?, component: String = #file) { - service.fatal(reason.rawValue, detail, component: component) + public func fatal(_ reason: Reason, _ detail: String?, sourceFile: String = #file) { + service.fatal(reason.rawValue, detail, sourceFile: sourceFile) } } @@ -66,51 +66,51 @@ public extension Log { /// /// Convenience function that unwraps the error (if exists) and logs its description @discardableResult - static func optional(_ error: Error?, _ detail: String? = nil, component: String = #file) -> Bool { - shared.optional(error, detail, component: component) + static func optional(_ error: Error?, _ detail: String? = nil, sourceFile: String = #file) -> Bool { + shared.optional(error, detail, sourceFile: sourceFile) } /// Log a INFO message - static func info(_ string: String, component: String = #file) { - shared.info(string, component: component) + static func info(_ string: String, sourceFile: String = #file) { + shared.info(string, sourceFile: sourceFile) } /// Log a DEBUG message - static func debug(_ string: String, component: String = #file) { - shared.debug(string, component: component) + static func debug(_ string: String, sourceFile: String = #file) { + shared.debug(string, sourceFile: sourceFile) } /// Log a ERROR message /// /// Convencience function that categorize common errors that the app can handle - static func unexpected(_ reason: Reason, _ detail: String?, component: String = #file) { - shared.unexpected(reason, detail, component: component) + static func unexpected(_ reason: Reason, _ detail: String?, sourceFile: String = #file) { + shared.unexpected(reason, detail, sourceFile: sourceFile) } /// Log a FATAL message /// /// Convencience function that categorize common errors that the app cannot handle - static func fatal(_ reason: Reason, _ detail: String?, component: String = #file) { - shared.fatal(reason, detail, component: component) + static func fatal(_ reason: Reason, _ detail: String?, sourceFile: String = #file) { + shared.fatal(reason, detail, sourceFile: sourceFile) } /// Log a ERROR message /// /// Convenience function that unwraps an error and a response from a network call - static func optional(_ error: Error?, from response: URLResponse?, component: String = #file) { + static func optional(_ error: Error?, from response: URLResponse?, sourceFile: String = #file) { guard let error = error else { return } guard let response = response else { return } let path = response.url?.path ?? "unknown path" let detail = "\(path) \(error)" - shared.unexpected(.apiError, detail, component: component) + shared.unexpected(.apiError, detail, sourceFile: sourceFile) } /// Log a ERROR message - static func error(_ message: String, _ detail: String? = nil, component: String = #file) { - shared.error(message, component: component) + static func error(_ message: String, _ detail: String? = nil, sourceFile: String = #file) { + shared.error(message, sourceFile: sourceFile) } - static func error(_ error: Error, _ detail: String? = nil, component: String = #file) { - shared.optional(error, detail, component: component) + static func error(_ error: Error, _ detail: String? = nil, sourceFile: String = #file) { + shared.optional(error, detail, sourceFile: sourceFile) } } diff --git a/Sources/Delivery/Models/LogProtocol.swift b/Sources/Delivery/Models/LogProtocol.swift index 8ce9b1a..b422e07 100644 --- a/Sources/Delivery/Models/LogProtocol.swift +++ b/Sources/Delivery/Models/LogProtocol.swift @@ -17,24 +17,24 @@ public protocol LogProtocol { /// /// Convenience function that unwraps the error (if exists) and logs its description @discardableResult - func optional(_ error: Error?, _ detail: String?, component: String) -> Bool + func optional(_ error: Error?, _ detail: String?, sourceFile: String) -> Bool /// Log a INFO message - func info(_ string: String, component: String) + func info(_ string: String, sourceFile: String) /// Log a DEBUG message - func debug(_ string: String, component: String) + func debug(_ string: String, sourceFile: String) /// Log a ERROR message - func error(_ string: String, component: String) + func error(_ string: String, sourceFile: String) /// Log a ERROR message /// /// Convencience function that categorize common errors that the app can handle - func unexpected(_ reason: Reason, _ detail: String?, component: String) + func unexpected(_ reason: Reason, _ detail: String?, sourceFile: String) /// Log a FATAL message /// /// Convencience function that categorize common errors that the app cannot handle - func fatal(_ reason: Reason, _ detail: String?, component: String) + func fatal(_ reason: Reason, _ detail: String?, sourceFile: String) } diff --git a/Sources/Domain/Services/LoggerService.swift b/Sources/Domain/Services/LoggerService.swift index 640f697..3a9dfbb 100644 --- a/Sources/Domain/Services/LoggerService.swift +++ b/Sources/Domain/Services/LoggerService.swift @@ -11,13 +11,13 @@ protocol LoggerService { var fileUrls: [URL] { get } - func debug(_ string: String, component: String) + func debug(_ string: String, sourceFile: String) - func info(_ string: String, component: String) + func info(_ string: String, sourceFile: String) - func optional(_ error: Error?, _ detail: String?, component: String) -> Bool + func optional(_ error: Error?, _ detail: String?, sourceFile: String) -> Bool - func unexpected(_ reason: String, _ detail: String?, component: String) + func unexpected(_ reason: String, _ detail: String?, sourceFile: String) - func fatal(_ reason: String, _ detail: String?, component: String) + func fatal(_ reason: String, _ detail: String?, sourceFile: String) } diff --git a/Sources/Domain/Services/LoggerServiceAdapter.swift b/Sources/Domain/Services/LoggerServiceAdapter.swift index 80bdc33..74f5d36 100644 --- a/Sources/Domain/Services/LoggerServiceAdapter.swift +++ b/Sources/Domain/Services/LoggerServiceAdapter.swift @@ -25,51 +25,52 @@ class LoggerServiceAdapter: LoggerService { fileLoggerService.fileUrls } - func debug(_ string: String, component: String) { + func debug(_ string: String, sourceFile: String) { let message = "LOG:DEBUG: \(string)" fileLoggerService.debug(message) - let osLogger = logger(for: component) + let osLogger = logger(for: sourceFile) osLogger.debug("\(string)") } - func info(_ string: String, component: String) { + func info(_ string: String, sourceFile: String) { let message = "LOG:INFO: \(string)" fileLoggerService.info(message) - let osLogger = logger(for: component) + let osLogger = logger(for: sourceFile) osLogger.info("\(string)") } - func optional(_ error: Error?, _ detail: String?, component: String) -> Bool { + func optional(_ error: Error?, _ detail: String?, sourceFile: String) -> Bool { guard let error = error else { return false } let message = "LOG:ERROR:\(detail ?? "") \(error)" fileLoggerService.error(message) - let osLogger = logger(for: component) + let osLogger = logger(for: sourceFile) osLogger.error("\(detail ?? "") \(error)") return true } - func unexpected(_ reason: String, _ detail: String?, component: String) { + func unexpected(_ reason: String, _ detail: String?, sourceFile: String) { let message = "LOG:UNEXPECTED:\(reason) \(detail ?? "")" fileLoggerService.error(message) - let osLogger = logger(for: component) + let osLogger = logger(for: sourceFile) osLogger.error("\(reason) \(detail ?? "")") } - func fatal(_ reason: String, _ detail: String?, component: String) { + func fatal(_ reason: String, _ detail: String?, sourceFile: String) { let message = "LOG:FATAL:\(reason) \(detail ?? "")" fileLoggerService.error(message) - let osLogger = logger(for: component) + let osLogger = logger(for: sourceFile) osLogger.error("\(reason) \(detail ?? "")") } - private func logger(for component: String) -> Logger { - if let logger = loggers[component] { + private func logger(for sourceFile: String) -> Logger { + let className = (sourceFile as NSString).lastPathComponent.replacingOccurrences(of: ".swift", with: "") + if let logger = loggers[className] { return logger } else { - let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: component) - loggers[component] = logger + let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: className) + loggers[className] = logger return logger } }