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()
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.

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

Module-scoped logging utilities for Julia built on top of the stdlib Logging. This package provides:

  • A ComponentLogger with hierarchical rule keys to control log levels per component path, e.g. (:net, :http).
  • Lightweight functions clog, clogenabled, clogf for emitting messages and checking if logging is enabled.
  • Macros @clog, @clogf, @clogenabled that capture the caller module/source location for accurate provenance.
  • Macro @forward_logger to generate module-local forwarding methods.
  • A simple PlainLogger sink 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")
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.
  • lock: protects concurrent access to rules.
  • min_level: atomic cache of the minimum value in rules 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/timestamps, with minimal coloring by level.

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

source
ComponentLogging.set_log_level!Function
set_log_level!(logger, group, lvl) -> 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 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.

source
ComponentLogging.with_min_levelFunction
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.

source