Skip to content

Commit 3357dd9

Browse files
authored
feat: Adopt swift-log (#47)
1 parent 3d408b8 commit 3357dd9

File tree

3 files changed

+127
-15
lines changed

3 files changed

+127
-15
lines changed

Package.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,17 @@ let package = Package(
2828
targets: ["LoggerAPI"]
2929
)
3030
],
31+
dependencies: [
32+
// Note: Syntax to allow compatibility with both Swift 4 and Swift 5 projects.
33+
// See: https://github.com/apple/swift-log#help-i-need-swift-4
34+
.package(url: "https://github.com/apple/swift-log.git", Version("0.0.0") ..< Version("2.0.0")),
35+
],
3136
targets: [
3237
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
3338
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
3439
.target(
35-
name: "LoggerAPI"
36-
)
40+
name: "LoggerAPI",
41+
dependencies: ["Logging"]
42+
),
3743
]
3844
)

Package@swift-4.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,17 @@ let package = Package(
2828
targets: ["LoggerAPI"]
2929
)
3030
],
31+
dependencies: [
32+
// Note: Syntax to allow compatibility with both Swift 4 and Swift 5 projects.
33+
// See: https://github.com/apple/swift-log#help-i-need-swift-4
34+
.package(url: "https://github.com/apple/swift-log.git", Version("0.0.0") ..< Version("2.0.0")),
35+
],
3136
targets: [
3237
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
3338
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
3439
.target(
35-
name: "LoggerAPI"
36-
)
40+
name: "LoggerAPI",
41+
dependencies: ["Logging"]
42+
),
3743
]
3844
)

Sources/LoggerAPI/Logger.swift

Lines changed: 111 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright IBM Corporation 2016, 2017
2+
* Copyright IBM Corporation 2016 - 2019
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -14,6 +14,9 @@
1414
* limitations under the License.
1515
**/
1616

17+
import Logging
18+
import Foundation
19+
1720
/// Implement the `CustomStringConvertible` protocol for the `LoggerMessageType` enum
1821
extension LoggerMessageType: CustomStringConvertible {
1922
/// Convert a `LoggerMessageType` into a printable format.
@@ -64,12 +67,49 @@ public protocol Logger {
6467

6568
}
6669

70+
extension NSLock {
71+
func withLock<T>(_ body: () throws -> T) rethrows -> T {
72+
self.lock()
73+
defer {
74+
self.unlock()
75+
}
76+
return try body()
77+
}
78+
}
79+
6780
/// A class of static members used by anyone who wants to log messages.
6881
public class Log {
6982

83+
private static var _logger: Logger?
84+
private static var _loggerLock: NSLock = NSLock()
85+
7086
/// An instance of the logger. It should usually be the one and only reference
7187
/// of the `Logger` protocol implementation in the system.
72-
public static var logger: Logger?
88+
/// This can be used in addition to `swiftLogger`, in which case log messages
89+
/// will be sent to both loggers.
90+
public static var logger: Logger? {
91+
get {
92+
return self._loggerLock.withLock { self._logger }
93+
}
94+
set {
95+
self._loggerLock.withLock { self._logger = newValue }
96+
}
97+
}
98+
99+
private static var _swiftLogger: Logging.Logger?
100+
private static var _swiftLoggerLock: NSLock = NSLock()
101+
102+
/// An instance of a swift-log Logger. If set, LoggerAPI will direct log messages
103+
/// to swift-log. This can be used in addition to `logger`, in which case log
104+
/// messages will be sent to both loggers.
105+
public static var swiftLogger: Logging.Logger? {
106+
get {
107+
return self._swiftLoggerLock.withLock { self._swiftLogger }
108+
}
109+
set {
110+
self._swiftLoggerLock.withLock { self._swiftLogger = newValue }
111+
}
112+
}
73113

74114
/// Log a message for use when in verbose logging mode.
75115
///
@@ -89,6 +129,7 @@ public class Log {
89129
logger.log( .verbose, msg: msg(),
90130
functionName: functionName, lineNum: lineNum, fileName: fileName)
91131
}
132+
swiftLogger?.info("\(msg())")
92133
}
93134

94135
/// Log an informational message.
@@ -109,6 +150,7 @@ public class Log {
109150
logger.log( .info, msg: msg(),
110151
functionName: functionName, lineNum: lineNum, fileName: fileName)
111152
}
153+
swiftLogger?.notice("\(msg())")
112154
}
113155

114156
/// Log a warning message.
@@ -127,8 +169,9 @@ public class Log {
127169
lineNum: Int = #line, fileName: String = #file) {
128170
if let logger = logger, logger.isLogging(.warning) {
129171
logger.log( .warning, msg: msg(),
130-
functionName: functionName, lineNum: lineNum, fileName: fileName)
172+
functionName: functionName, lineNum: lineNum, fileName: fileName)
131173
}
174+
swiftLogger?.warning("\(msg())")
132175
}
133176

134177
/// Log an error message.
@@ -147,8 +190,9 @@ public class Log {
147190
lineNum: Int = #line, fileName: String = #file) {
148191
if let logger = logger, logger.isLogging(.error) {
149192
logger.log( .error, msg: msg(),
150-
functionName: functionName, lineNum: lineNum, fileName: fileName)
193+
functionName: functionName, lineNum: lineNum, fileName: fileName)
151194
}
195+
swiftLogger?.error("\(msg())")
152196
}
153197

154198
/// Log a debugging message.
@@ -167,8 +211,9 @@ public class Log {
167211
lineNum: Int = #line, fileName: String = #file) {
168212
if let logger = logger, logger.isLogging(.debug) {
169213
logger.log( .debug, msg: msg(),
170-
functionName: functionName, lineNum: lineNum, fileName: fileName)
214+
functionName: functionName, lineNum: lineNum, fileName: fileName)
171215
}
216+
swiftLogger?.debug("\(msg())")
172217
}
173218

174219
/// Log a message when entering a function.
@@ -187,8 +232,9 @@ public class Log {
187232
lineNum: Int = #line, fileName: String = #file) {
188233
if let logger = logger, logger.isLogging(.entry) {
189234
logger.log(.entry, msg: msg(),
190-
functionName: functionName, lineNum: lineNum, fileName: fileName)
235+
functionName: functionName, lineNum: lineNum, fileName: fileName)
191236
}
237+
swiftLogger?.trace("\(msg())")
192238
}
193239

194240
/// Log a message when exiting a function.
@@ -207,23 +253,77 @@ public class Log {
207253
lineNum: Int = #line, fileName: String = #file) {
208254
if let logger = logger, logger.isLogging(.exit) {
209255
logger.log(.exit, msg: msg(),
210-
functionName: functionName, lineNum: lineNum, fileName: fileName)
256+
functionName: functionName, lineNum: lineNum, fileName: fileName)
211257
}
258+
swiftLogger?.trace("\(msg())")
212259
}
213260

214-
/// Indicates if a message with a specified type (`LoggerMessageType`) will be in the logger
215-
/// output (i.e. will not be filtered out).
261+
/// Indicates if a message with a specified type (`LoggerMessageType`) will be logged
262+
/// by some configured logger (i.e. will not be filtered out). This could be a Logger
263+
/// conforming to LoggerAPI, swift-log or both.
216264
///
217-
/// - Parameter type: The type of message (`LoggerMessageType`).
265+
/// Note that due to differences in the log levels defined by LoggerAPI and swift-log,
266+
/// their equivalence is mapped as follows:
267+
/// ```
268+
/// LoggerAPI: swift-log:
269+
/// .error -> .error
270+
/// .warning -> .warning
271+
/// .info -> .notice
272+
/// .verbose -> .info
273+
/// .debug -> .debug
274+
/// .entry -> .trace
275+
/// .exit -> .trace
276+
/// ```
277+
///
278+
/// For example, a swift-log Logger configured to log at the `.notice` level will log
279+
/// messages from LoggerAPI at a level of `.info` or higher.
280+
///
281+
/// - Parameter level: The type of message (`LoggerMessageType`).
218282
///
219283
/// - Returns: A Boolean indicating whether a message of the specified type
220-
/// (`LoggerMessageType`) will be in the logger output.
284+
/// (`LoggerMessageType`) will be logged.
221285
public class func isLogging(_ level: LoggerMessageType) -> Bool {
286+
return isLoggingToLoggerAPI(level) || isLoggingToSwiftLog(level)
287+
}
288+
289+
/// Indicates whether a LoggerAPI Logger is configured to log at the specified level.
290+
///
291+
/// - Parameter level: The type of message (`LoggerMessageType`).
292+
///
293+
/// - Returns: A Boolean indicating whether a message of the specified type
294+
/// will be logged via the registered `LoggerAPI.Logger`.
295+
private class func isLoggingToLoggerAPI(_ level: LoggerMessageType) -> Bool {
222296
guard let logger = logger else {
223297
return false
224298
}
225299
return logger.isLogging(level)
226300
}
301+
302+
/// Indicates whether a swift-log Logger is configured to log at the specified level.
303+
///
304+
/// - Parameter level: The type of message (`LoggerMessageType`).
305+
///
306+
/// - Returns: A Boolean indicating whether a message of the specified type
307+
/// will be logged via the registered `Logging.Logger`.
308+
private class func isLoggingToSwiftLog(_ level: LoggerMessageType) -> Bool {
309+
guard let logger = swiftLogger else {
310+
return false
311+
}
312+
switch level {
313+
case .error:
314+
return logger.logLevel <= .error
315+
case .warning:
316+
return logger.logLevel <= .warning
317+
case .info:
318+
return logger.logLevel <= .notice
319+
case .verbose:
320+
return logger.logLevel <= .info
321+
case .debug:
322+
return logger.logLevel <= .debug
323+
case .entry, .exit:
324+
return logger.logLevel <= .trace
325+
}
326+
}
227327
}
228328

229329
/// The type of a particular log message. It is passed with the message to be logged to the

0 commit comments

Comments
 (0)