11module ComponentLogging
22using Logging
3+ using Threads: Atomic
34
45include (" PlainLogger.jl" )
56export PlainLogger
@@ -19,14 +20,16 @@ msg_to_tuple(x::Tuple) = x
1920msg_to_tuple (x) = (x,)
2021
2122# # ComponentLogger
22- mutable struct ComponentLogger{L<: AbstractLogger } <: AbstractLogger
23- const rules:: Dict{RuleKey,LogLevel}
24- const sink:: L
25- min:: LogLevel
23+ struct ComponentLogger{L<: AbstractLogger } <: AbstractLogger
24+ rules:: Dict{RuleKey,LogLevel}
25+ sink:: L
26+ lock:: ReentrantLock
27+ min_level:: Atomic{Int32}
2628end
2729
2830function ComponentLogger (rules:: Dict{RuleKey,LogLevel} = Dict {RuleKey,LogLevel} ((DEFAULT_SYM,) => Info); sink= ConsoleLogger (Debug))
29- return ComponentLogger (rules, sink, minimum (values (rules)))
31+ rules = copy (rules)
32+ return ComponentLogger (rules, sink, ReentrantLock (), minimum (values (rules)). level)
3033end
3134
3235function ComponentLogger (nonstdrules:: AbstractDict ; sink= ConsoleLogger (Debug))
4346function set_log_level! (logger:: ComponentLogger , group, lvl:: Union{Integer,LogLevel} )
4447 grp = _tokey (group)
4548 lv = LogLevel (lvl)
46- old = get (logger. rules, grp, nothing )
47- logger. rules[grp] = lv
48- if lv < logger. min
49- logger. min = lv
50- elseif old != = nothing && old === logger. min && lv > logger. min
51- logger. min = minimum (values (logger. rules))
49+ @lock logger. lock begin
50+ old = get (logger. rules, grp, nothing )
51+ minlvl = LogLevel (logger. min_level[])
52+ if lv < minlvl
53+ logger. min_level[] = lv. level
54+ logger. rules[grp] = lv
55+ else
56+ logger. rules[grp] = lv
57+ if old != = nothing && old === minlvl && lv > minlvl
58+ logger. min_level[] = minimum (values (logger. rules)). level
59+ end
60+ end
5261 end
5362 return logger
5463end
5564
5665set_log_level! (logger:: ComponentLogger , group, on:: Bool ) =
5766 set_log_level! (logger, group, on ? 0 : 1 )
5867
59- " Temporarily set the minimum level within a do-block; restore afterward even if an exception is thrown; no lock"
60- function with_min_level (f:: Function , logger:: ComponentLogger , lvl:: Union{Integer,LogLevel} )
61- old_lvl = logger. min
62- logger. min = LogLevel (lvl)
63- try
64- f ()
65- finally
66- logger. min = old_lvl
67- end
68- end
68+ " Temporarily set the minimum level for the current task within a do-block; restore afterward even if an exception is thrown"
69+ with_min_level (f:: Function , logger:: ComponentLogger , lvl:: Union{Integer,LogLevel} ) =
70+ task_local_storage (f, logger, LogLevel (lvl))
6971
7072@inline function _effective_level (rules:: Dict{RuleKey,LogLevel} , group:: Union{Symbol,RuleKey} ):: LogLevel
7173 path = _tokey (group) # ::NTuple{N,Symbol}
9294 end
9395end
9496
95- Logging. min_enabled_level (g:: ComponentLogger ) = g. min
97+ function Logging. min_enabled_level (g:: ComponentLogger ):: LogLevel
98+ lvl = get (task_local_storage (), g, nothing ):: Union{Nothing,LogLevel}
99+ return lvl === nothing ? LogLevel (g. min_level[]) : lvl
100+ end
96101
97102Logging. shouldlog (g:: ComponentLogger , level, _module, group, id) =
98- level >= _effective_level (g. rules, group)
103+ @lock g . lock level >= _effective_level (g. rules, group)
99104
100105Logging. handle_message (logger:: ComponentLogger , level:: LogLevel , message, _module, group, id, file, line; kwargs... ) =
101106 Logging. handle_message (logger. sink, level, message, _module, group, id, file, line; kwargs... )
102107
103108# # Module registry
104- const _REGISTRY_LOCK = ReentrantLock ()
105- const _REGISTRY = IdDict {Module,AbstractLogger} ()
109+ const _RegistryLock = ReentrantLock ()
110+ const _Registry = IdDict {Module,AbstractLogger} ()
106111
107112function set_module_logger (mod:: Module , logger:: AbstractLogger ):: String
108- lock (_REGISTRY_LOCK) do
109- _REGISTRY[mod] = logger
110- end
113+ @lock _RegistryLock _Registry[mod] = logger
111114 string (mod) * " <- " * string (typeof (logger))
112115end
113116
114117" Get the logger for the calling module; if unbound, fallback through parent modules; error at the top"
115118function get_logger (mod:: Module )
116- lock (_REGISTRY_LOCK) do
119+ @ lock _RegistryLock begin
117120 m = mod
118121 while true
119- if haskey (_REGISTRY , m)
120- return _REGISTRY [m]
122+ if haskey (_Registry , m)
123+ return _Registry [m]
121124 end
122125 pm = parentmodule (m)
123126 if pm === m # reached the top (e.g. Base/Core/Main)
@@ -268,14 +271,15 @@ function _print_tree(io::IO, rules::Dict{RuleKey,LogLevel};
268271end
269272
270273function Base. show (io:: IO , :: MIME"text/plain" , logger:: ComponentLogger )
274+ rules, minlvl = @lock logger. lock (copy (logger. rules), LogLevel (logger. min_level[]))
271275 println (io, " ComponentLogger" )
272276 print (io, " sink:\t " )
273277 println (io, nameof (typeof (logger. sink)))
274278 print (io, " min:\t " )
275- _print_level (io, logger . min )
279+ _print_level (io, minlvl )
276280 println (io)
277- println (io, " rules:\t " , length (logger . rules))
278- _print_tree (io, logger . rules)
281+ println (io, " rules:\t " , length (rules))
282+ _print_tree (io, rules)
279283end
280284
281285include (" helpers.jl" )
0 commit comments