@@ -7,52 +7,75 @@ import Foundation
77
88// MARK: - Logger
99
10- /// A class responsible for logging functionality.
10+ /// A high-level logging coordinator responsible for filtering and dispatching log messages.
11+ ///
12+ /// `Logger` acts as the central entry point for the logging system. It evaluates whether a message
13+ /// should be logged based on the current `logLevel` and then broadcasts allowed messages
14+ /// to a collection of `IPrinterStrategy` implementations.
1115open class Logger {
1216 // MARK: Properties
1317
14- /// The current log level for this logger.
15- private var _logLevel : Atomic < LogLevel >
18+ /// A recursive lock used to synchronize access to the logger's mutable state .
19+ private let lock = NSRecursiveLock ( )
1620
17- /// The current log level for this logger.
21+ /// Internal storage for the log level, protected by a lock.
22+ private var _logLevel : LogLevel
23+
24+ /// The active log level configuration for this logger.
25+ ///
26+ /// This property uses a lock to ensure thread-safe read and write access.
1827 public var logLevel : LogLevel {
19- get { _logLevel. value }
20- set { _logLevel. value = newValue }
28+ lock. lock ( )
29+ defer { lock. unlock ( ) }
30+ return _logLevel
2131 }
2232
23- /// An array of printer strategies to handle the log output .
33+ /// The collection of output strategies (printers) that handle the actual delivery of log messages .
2434 let printers : [ IPrinterStrategy ]
2535
26- // MARK: Initialization
36+ // MARK: - Initialization
2737
28- /// Initializes a new Logger instance.
38+ /// Initializes a new ` Logger` instance.
2939 ///
3040 /// - Parameters:
31- /// - printers: An array of printer strategies.
32- /// - logLevel: The initial log level .
41+ /// - printers: An array of strategies defining where logs should be sent (e.g., Console, OSLog, File) .
42+ /// - logLevel: The initial set of allowed log levels. Defaults to specific levels if not provided .
3343 public init (
3444 printers: [ IPrinterStrategy ] ,
3545 logLevel: LogLevel
3646 ) {
3747 self . printers = printers
38- _logLevel = Atomic ( value: logLevel)
48+ _logLevel = logLevel
49+ }
50+
51+ /// Atomically updates the current log level using a transformation closure.
52+ ///
53+ /// This method prevents race conditions that can occur when multiple threads try to
54+ /// modify the `logLevel` simultaneously (e.g., two threads trying to add different flags at once).
55+ ///
56+ /// - Parameter transform: A closure that receives the current `LogLevel` and returns the new desired value.
57+ public func updateLogLevel( _ transform: ( LogLevel ) -> LogLevel ) {
58+ lock. lock ( )
59+ defer { lock. unlock ( ) }
60+ _logLevel = transform ( _logLevel)
3961 }
4062
41- // MARK: Private
63+ // MARK: - Private Methods
4264
43- /// Passes the message to each receiver's printer .
65+ /// Dispatches a message to all registered printers if the log level is enabled .
4466 ///
4567 /// - Parameters:
46- /// - message: The message to dispatch .
47- /// - logLevel: The message's level.
68+ /// - message: The string content to log .
69+ /// - logLevel: The severity level associated with this message .
4870 private func log( _ message: String , logLevel: LogLevel ) {
4971 guard isLoggerEnabled ( for: logLevel) else { return }
5072 printers. forEach { $0. log ( message, logLevel: logLevel) }
5173 }
5274
53- /// Checks if the given `LogLevel` is allowed by the receiver .
75+ /// Evaluates whether the current logger configuration allows a specific log level .
5476 ///
55- /// - Parameter logLevel: The log level to check.
77+ /// - Parameter logLevel: The level to validate against the current settings.
78+ /// - Returns: `true` if the level is included in the active `logLevel` set.
5679 private func isLoggerEnabled( for logLevel: LogLevel ) -> Bool {
5780 self . logLevel. contains ( logLevel)
5881 }
@@ -61,18 +84,26 @@ open class Logger {
6184// MARK: ILogger
6285
6386extension Logger : ILogger {
87+ /// Logs a message for debugging purposes.
88+ /// - Parameter message: A closure returning the string to log, evaluated only if `.debug` is enabled.
6489 public func debug( message: @autoclosure ( ) -> String ) {
6590 log ( message ( ) , logLevel: . debug)
6691 }
6792
93+ /// Logs an informational message highlighting application progress.
94+ /// - Parameter message: A closure returning the string to log, evaluated only if `.info` is enabled.
6895 public func info( message: @autoclosure ( ) -> String ) {
6996 log ( message ( ) , logLevel: . info)
7097 }
7198
99+ /// Logs a critical fault that may require system-level attention.
100+ /// - Parameter message: A closure returning the string to log, evaluated only if `.fault` is enabled.
72101 public func fault( message: @autoclosure ( ) -> String ) {
73102 log ( message ( ) , logLevel: . fault)
74103 }
75104
105+ /// Logs an error that occurred during execution.
106+ /// - Parameter message: A closure returning the string to log, evaluated only if `.error` is enabled.
76107 public func error( message: @autoclosure ( ) -> String ) {
77108 log ( message ( ) , logLevel: . error)
78109 }
0 commit comments