Common Types and Configuration
ComponentLogger
ComponentLogger is the central router/filter in ComponentLogging. It associates hierarchical group keys with minimum integer 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(
:solver => 1000,
(:solver, :iteration) => -2000,
); sink=PlainLogger())Here :solver and unmatched descendants require level 1000, while (:solver, :iteration) accepts level -2000 and above.
display(logger) prints the configured hierarchy as a tree.
Concurrency and ownership
ComponentLogger is safe to share across tasks and threads. Rule updates are serialized and published as atomic copy-on-write snapshots, while normal reads remain lock-free. Each snapshot includes a cached minimum level for fast rejection.
Thread safety was introduced in v0.2.0. High-performance copy-on-write snapshots were introduced in v0.3.0.
The logger owns routing/filtering state, not final output. Accepted records are delegated to logger.sink; output thread safety therefore depends on the sink.
Changing rules
Use set_log_level! to update rules:
set_log_level!(logger, :solver, 1000)
set_log_level!(logger, (:solver, :iteration), -2000)Multiple group, level pairs are applied atomically in one update:
set_log_level!(logger,
:solver, 1000,
(:solver, :iteration), -2000,
(:solver, :heuristics), false,
)Boolean levels provide a compact switch interface. true maps to 0; false maps to 1, which pairs naturally with the no-level clogenabled(logger, group) check. See Hierarchical Runtime Control for broader use of this mechanism.
set_log_level!(logger, (:solver, :heuristics), true)
set_log_level!(logger, (:solver, :heuristics), false)Inspecting effective levels
Use get_log_level to query a group's effective level after hierarchical lookup.
logger = ComponentLogger(Dict(:solver => 1000))
get_log_level(logger, (:solver, :iteration))
# WarnTemporary 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
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.
The temporary level applies to every task and thread using that logger. The old snapshot is restored even if the callback throws, so configuration changes to the same logger inside the callback do not persist afterward.
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.
sink = PlainLogger()
logger = ComponentLogger(Dict(:core => 0); sink)
clog(logger, :core, 0, "hello")Routing and presentation are intentionally separate: ComponentLogger applies its component rules, while PlainLogger (or any other AbstractLogger sink) applies its own filtering and decides how accepted records are written.
Reference
ComponentLogging.ComponentLogging — Module
ComponentLoggingHierarchical component logging built on Julia's standard Logging interface. This package provides:
- A
ComponentLoggerwith hierarchical rule keys to control log levels per component path, e.g.(:net, :http). - Explicit functions
clogandclogenabled. - Explicit logging macros
@clog,@cdebug,@cinfo,@cwarn, and@cerrorwith caller metadata. @forward_logger, which creates module-local forwarding functions and a local@clog.- A simple
PlainLoggersink for plain output without timestamps or standard prefixes.
Typical usage:
using ComponentLogging
rules = Dict(
:core => 0,
:io => 1000,
:net => -2000,
)
clogger = ComponentLogger(rules; sink=PlainLogger())
clog(clogger, :core, 0, "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.- Configuration updates are serialized and published as atomic copy-on-write (COW) snapshots.
- Each snapshot includes a
min_levelcache for fast checks.
ComponentLogging.PlainLogger — Type
PlainLogger(; stream=Base.CoreLogging.closed_stream, min_level=Info)A simple AbstractLogger implementation that prints messages without standard prefixes or timestamps.
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.
When used as a ComponentLogger sink, a record must pass both the effective component level and PlainLogger.min_level.
ComponentLogging.set_log_level! — Function
set_log_level!(logger, group, lvl, args...) -> 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, Integer, or Bool. Additional args... are accepted as more group, level pairs and are applied atomically in one update.
If a level is a Bool, it is treated as a simple switch: true sets the rule to 0 and false sets it to 1 (which disables the default clogenabled(logger, group) check).
Rule updates are thread-safe and atomic.
Example:
logger = ComponentLogger()
set_log_level!(logger, :solver, 1000, (:solver, :iteration), -1000)ComponentLogging.get_log_level — Function
get_log_level(logger, group) -> LogLevelReturn the effective minimum log level for group on logger. group may be a Symbol or an NTuple{N,Symbol} component path. Lookup checks the exact path, then its parent paths, and finally (:__default__,).
Example:
logger = ComponentLogger(Dict(:solver => 1000))
get_log_level(logger, (:solver, :iteration))
# WarnComponentLogging.with_min_level — Function
with_min_level(f, logger, lvl)Temporarily override the minimum enabled level for logger while executing f(). The override applies to every task and thread that uses this logger, and the previous state is restored when f() returns or throws. Configuration changes made to the logger during the callback are discarded when that state is restored.