Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement scoped loggers from ModuleLoggers 🍰 #230

Merged
merged 1 commit into from
Apr 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions Sources/Logging/Loggers/ModuleLogger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,41 @@ public extension ModuleLogger where Self: LogDestination {
}
}
}

public extension ModuleLogger {

/// Scopes the logger to one that sends all log events from a single `module` via `self`.
///
/// This can be useful when we need to pass in a simple `Logger` instance but want log events forwarded to a
/// larger logging infrastructure (e.g. with multiple modules), under a single module.
///
/// - Parameter module: The module to scope log events with.
/// - Returns: A new logger that sends all events with the chosen `module` to `self`.
func scopedLogger(for module: Module) -> Logger { Log.ForwardingLogger(scoping: module, from: self) }
}

private extension Log {

final class ForwardingLogger: Logger {

let upstreamLog: (Log.Level, () -> String, StaticString, UInt, StaticString) -> Void

init<L: ModuleLogger>(scoping module: L.Module, from logger: L) {

self.upstreamLog = { level, message, file, line, function in
logger.log(module: module, level: level, message: message(), file: file, line: line, function: function)
}
}

func log(
level: Log.Level,
message: @autoclosure () -> String,
file: StaticString,
line: UInt,
function: StaticString
) {

upstreamLog(level, message, file, line, function)
}
}
}
82 changes: 82 additions & 0 deletions Tests/AlicerceTests/Logging/Loggers/ModuleLoggerTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,88 @@ class ModuleLoggerTestCase: XCTestCase {

log.error("message", file: "filename.ext", line: 1337, function: "function")
}

// scopedLogger(for:)

func testScopedLogger_WithVerboseLog_ShouldInvokeUpstreamLogWithCorrectModuleAndLogLevel() {

let scopedLogger = log.scopedLogger(for: .🤖)

log.moduleLogInvokedClosure = { module, level, message, file, line, function in
XCTAssertEqual(module, MockModule.🤖)
XCTAssertEqual(level, .verbose)
XCTAssertEqual(message, "message")
XCTAssertEqual(file.description, "filename.ext")
XCTAssertEqual(line, 1337)
XCTAssertEqual(function.description, "function")
}

scopedLogger.verbose("message", file: "filename.ext", line: 1337, function: "function")
}

func testScopedLogger_WithDebugLog_ShouldInvokeUpstreamLogWithCorrectModuleAndLogLevel() {

let scopedLogger = log.scopedLogger(for: .🤖)

log.moduleLogInvokedClosure = { module, level, message, file, line, function in
XCTAssertEqual(module, MockModule.🤖)
XCTAssertEqual(level, .debug)
XCTAssertEqual(message, "message")
XCTAssertEqual(file.description, "filename.ext")
XCTAssertEqual(line, 1337)
XCTAssertEqual(function.description, "function")
}

scopedLogger.debug("message", file: "filename.ext", line: 1337, function: "function")
}

func testScopedLogger_WithInfoLog_ShouldInvokeUpstreamLogWithCorrectModuleAndLogLevel() {

let scopedLogger = log.scopedLogger(for: .🤖)

log.moduleLogInvokedClosure = { module, level, message, file, line, function in
XCTAssertEqual(module, MockModule.🤖)
XCTAssertEqual(level, .info)
XCTAssertEqual(message, "message")
XCTAssertEqual(file.description, "filename.ext")
XCTAssertEqual(line, 1337)
XCTAssertEqual(function.description, "function")
}

scopedLogger.info("message", file: "filename.ext", line: 1337, function: "function")
}

func testScopedLogger_WithWarningLog_ShouldInvokeUpstreamLogWithCorrectModuleAndLogLevel() {

let scopedLogger = log.scopedLogger(for: .🤖)

log.moduleLogInvokedClosure = { module, level, message, file, line, function in
XCTAssertEqual(module, MockModule.🤖)
XCTAssertEqual(level, .warning)
XCTAssertEqual(message, "message")
XCTAssertEqual(file.description, "filename.ext")
XCTAssertEqual(line, 1337)
XCTAssertEqual(function.description, "function")
}

scopedLogger.warning("message", file: "filename.ext", line: 1337, function: "function")
}

func testScopedLogger_WithErrorLog_ShouldInvokeUpstreamLogWithCorrectModuleAndLogLevel() {

let scopedLogger = log.scopedLogger(for: .🤖)

log.moduleLogInvokedClosure = { module, level, message, file, line, function in
XCTAssertEqual(module, MockModule.🤖)
XCTAssertEqual(level, .error)
XCTAssertEqual(message, "message")
XCTAssertEqual(file.description, "filename.ext")
XCTAssertEqual(line, 1337)
XCTAssertEqual(function.description, "function")
}

scopedLogger.error("message", file: "filename.ext", line: 1337, function: "function")
}
}

private enum MockModule: String, LogModule {
Expand Down