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.

Info

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))
# Warn

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
    run_workload()
end

This 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.

Thread safety

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.ComponentLoggingModule
ComponentLogging

Hierarchical component logging built on Julia's standard Logging interface. This package provides:

  • A ComponentLogger with hierarchical rule keys to control log levels per component path, e.g. (:net, :http).
  • Explicit functions clog and clogenabled.
  • Explicit logging macros @clog, @cdebug, @cinfo, @cwarn, and @cerror with caller metadata.
  • @forward_logger, which creates module-local forwarding functions and a local @clog.
  • A simple PlainLogger sink 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")
source
ComponentLogging.ComponentLoggerType
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 from NTuple{N,Symbol} to LogLevel. If no explicit (:__default__,) rule exists, lookup falls back to Info.
  • sink: the underlying AbstractLogger that actually handles messages.
  • Configuration updates are serialized and published as atomic copy-on-write (COW) snapshots.
  • Each snapshot includes a min_level cache for fast checks.
source
ComponentLogging.PlainLoggerType
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 to stderr.
  • 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.

source
ComponentLogging.set_log_level!Function
set_log_level!(logger, group, lvl, args...) -> ComponentLogger

Set 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)
source
ComponentLogging.get_log_levelFunction
get_log_level(logger, group) -> LogLevel

Return 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))
# Warn
source
ComponentLogging.with_min_levelFunction
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.

source