Skip to content

Commit

Permalink
Fix LogDestination's Logger conformance log level filtering 🪵 (#248)
Browse files Browse the repository at this point in the history
When `Logger` conformance was added to `LogDestination`, we forgot to
filter logs according to the destination's `minLevel`, causing all logs
to be logged regardless of the level.

## Changes

- Add log level filtering to `LogDestination`'s `Logger` conformance,
as well as relevant UTs.

- Rename `Log.Level.isAbove(minLevel:)` helper to `meets(minLevel:)`.
  • Loading branch information
p4checo authored Jan 5, 2022
1 parent 21f56cb commit a1b58a2
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 5 deletions.
6 changes: 3 additions & 3 deletions Sources/Logging/Log.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ public enum Log {
case warning
case error

/// Checks if `self` is above the specified (minimum) log level. A message can be logged if its level is
/// Checks if `self` meets the specified (minimum) log level. A message can be logged if its level is
/// *greater than or equal* to another level defined as minimum.
///
/// The relationship between levels is as follows:
/// `.verbose` < `.debug` < `.info` < `.warning` < `.error`
///
/// - Parameter minLevel: The level to compare against `self`.
/// - Returns: `true` if `self` is above the given level, `false` otherwise.
func isAbove(minLevel: Level) -> Bool { minLevel.rawValue <= rawValue }
/// - Returns: `true` if `self` meets the minimum level, `false` otherwise.
func meets(minLevel: Level) -> Bool { rawValue >= minLevel.rawValue }
}

/// A queue object used to specify `DispatchQueue`'s used in log destinations, ensuring they are serial with the
Expand Down
4 changes: 2 additions & 2 deletions Sources/Logging/Loggers/Log+MultiLogger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,10 @@ extension Log {

// skip module checks for `nil` modules
if let module = module {
guard let moduleMinLevel = modules[module], level.isAbove(minLevel: moduleMinLevel) else { return }
guard let moduleMinLevel = modules[module], level.meets(minLevel: moduleMinLevel) else { return }
}

let matchingDestinations = destinations.filter { level.isAbove(minLevel: $0.minLevel) }
let matchingDestinations = destinations.filter { level.meets(minLevel: $0.minLevel) }

guard matchingDestinations.isEmpty == false else { return }

Expand Down
2 changes: 2 additions & 0 deletions Sources/Logging/Loggers/Logger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ public extension Logger where Self: LogDestination {
function: StaticString
) {

guard level.meets(minLevel: minLevel) else { return }

let item = Log.Item(
timestamp: Date(),
module: nil,
Expand Down
36 changes: 36 additions & 0 deletions Tests/AlicerceTests/Logging/Loggers/LoggerTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,42 @@ class LoggerTestCase: XCTestCase {

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

func testLog_WithLogDestinationAndLogLevelMeetingMinLevel_ShouldInvokeWrite() {

let minLevel = Log.Level.verbose
let level = Log.Level.error

XCTAssert(level.meets(minLevel: minLevel))

let log = MockLogDestination()
log.mockMinLevel = minLevel

log.writeInvokedClosure = { item, _ in
XCTAssertEqual(item.level, level)
XCTAssertEqual(item.message, "message")
XCTAssertEqual(item.file.description, "filename.ext")
XCTAssertEqual(item.line, 1337)
XCTAssertEqual(item.function.description, "function")
}

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

func testLog_WithLogDestinationAndLogLevelNotMeetingMinLevel_ShouldNotInvokeWrite() {

let minLevel = Log.Level.error
let level = Log.Level.verbose

XCTAssertFalse(level.meets(minLevel: minLevel))

let log = MockLogDestination()
log.mockMinLevel = minLevel

log.writeInvokedClosure = { _, _ in XCTFail("Unexpected write call") }

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

private enum MockModule: String, LogModule {
Expand Down

0 comments on commit a1b58a2

Please sign in to comment.