Common Types and Configuration
ComponentLogger
ComponentLogger is the central router/filter in ComponentLogging. It associates hierarchical group keys with minimum log levels and delegates accepted messages to an AbstractLogger sink.
Groups can be a Symbol or a tuple of symbols:
:solver
(:solver, :iteration)
(:solver, :linear_system)A more specific rule takes precedence over its parent. If no exact rule exists, lookup falls back through parent prefixes and finally to :__default__ (which defaults to Info when using the general dictionary constructor).
logger = ComponentLogger(Dict(
:__default__ => 0,
:solver => 1000,
(:solver, :iteration) => -1000,
); sink=PlainLogger())In this example, :solver and its unmatched descendants require Warn, while (:solver, :iteration) explicitly accepts Debug and above.
display(logger) prints the configured hierarchy in tree form, which is useful when inspecting a larger component configuration.
Concurrency and ownership
ComponentLogger is designed for shared concurrent use. Thread-safe configuration updates were introduced in v0.2.0; since v0.3.0, copy-on-write snapshots with atomic publication keep normal reads lock-free while configuration updates remain safe.
The logger owns routing/filtering state, not the final output mechanism. Accepted messages are delegated to logger.sink, so message-output thread safety depends on the selected sink.
Changing rules
Use set_log_level! to update one group dynamically:
set_log_level!(logger, :solver, 1000)
set_log_level!(logger, (:solver, :iteration), -1000)Boolean values provide a compact switch interface:
set_log_level!(logger, (:solver, :heuristics), true)
set_log_level!(logger, (:solver, :heuristics), false)true maps to level 0 (Info) and false maps to level 1, which pairs naturally with the no-level clogenabled(logger, group) check. See Hierarchical Runtime Control for broader use of this mechanism.
Temporary global minimum level
with_min_level temporarily changes the minimum level of one ComponentLogger for the duration of a callback:
with_min_level(logger, 2000) do
# The temporary minimum applies to every task/thread using this logger.
run_workload()
endThis is a logger-wide temporary override, not a task-local equivalent of Logging.with_logger. All users of the target logger observe the temporary minimum until the callback exits, after which the previous state is restored even if the callback throws.
Treat the block as a temporary configuration scope: configuration changes made to the same logger inside the block do not persist after the outer snapshot is restored.
PlainLogger
PlainLogger is an independent AbstractLogger sink that keeps console output close to ordinary print/println output instead of adding the standard [ Info:-style presentation. It can be used as the sink of a ComponentLogger or on its own with Julia's standard with_logger.
using ComponentLogging, Logging
sink = PlainLogger()
logger = ComponentLogger(Dict(:core => 0); sink)
clog(logger, :core, 0, "hello")Routing and presentation are intentionally separate: ComponentLogger decides whether a record passes, while PlainLogger (or any other AbstractLogger sink) decides how accepted records are written.
Reference
ComponentLogging.ComponentLogging — Module
ComponentLoggingModule-scoped logging utilities for Julia built on top of the stdlib Logging. This package provides:
- A
ComponentLoggerwith hierarchical rule keys to control log levels per component path, e.g.(:net, :http). - Lightweight functions
clog,clogenabled,clogffor emitting messages and checking if logging is enabled. - Macros
@clog,@clogf,@clogenabledthat capture the caller module/source location for accurate provenance. - Macro
@forward_loggerto generate module-local forwarding methods. - A simple
PlainLoggersink for pretty, colored output without timestamps/prefixes.
Typical usage:
using ComponentLogging
rules = Dict(
:core => Info,
:io => Warn,
:net => Debug
)
clogger = ComponentLogger(rules; sink=PlainLogger())
clog(clogger, :core, Info, "something happened")ComponentLogging.ComponentLogger — Type
ComponentLogger(; sink=ConsoleLogger(Debug))
ComponentLogger(rules::AbstractDict; sink=ConsoleLogger(Debug))A logger that delegates to an underlying sink (AbstractLogger) while applying component-based minimum level rules. Rules are defined on paths of symbols (NTuple{N,Symbol}). A lookup walks up the path and falls back to (:__default__,).
rules: mapping fromNTuple{N,Symbol}toLogLevel. If no explicit(:__default__,)rule exists, lookup falls back toInfo.sink: the underlyingAbstractLoggerthat actually handles messages.lock: protects concurrent access torules.min_level: atomic cache of the minimum value inrulesfor fast checks.
ComponentLogging.PlainLogger — Type
PlainLogger(; stream=Base.CoreLogging.closed_stream, min_level=Info)A simple AbstractLogger implementation that prints messages without standard prefixes/timestamps, with minimal coloring by level.
stream::IO: target stream; if closed, falls back tostderr.min_level::LogLevel: minimum enabled level for the sink.
Intended for tests, demos, or embedding in custom sinks.
ComponentLogging.set_log_level! — Function
set_log_level!(logger, group, lvl) -> ComponentLoggerSet or update the minimum level for a specific component group on logger. group may be a Symbol or a NTuple{N,Symbol} tuple; lvl can be LogLevel or Integer. If lvl is a Bool, it is treated as a simple switch: true sets the rule to Info and false sets it to LogLevel(1) (which disables the default clogenabled(logger, group) check). Updates rules under logger.lock and keeps the atomic min_level cache consistent.
ComponentLogging.with_min_level — Function
with_min_level(f, logger, lvl)Temporarily override the minimum enabled level for the current task while executing f(). The override is task-local, so it does not modify logger.min_level or affect other concurrent tasks. Nested overrides are restored correctly, including when f() throws an exception.