-
-
Notifications
You must be signed in to change notification settings - Fork 0
Configuring Loggers
Chris Michael edited this page Sep 29, 2026
·
1 revision
Configuration.create() keeps Information and above and writes nowhere; Configuration.nested() keeps every level, for a sub-logger whose parent already decided which events arrive. Each method answers a new configuration, so a base can be shared and extended.
| Method | Decision |
|---|---|
minimumLevel, controlledBy
|
the minimum level, fixed or through a LevelSwitch
|
overrideLevel, overrideSwitch
|
the minimum for a source prefix; the most specific prefix decides |
writeTo, writeToAtLeast, writeToControlled, writeToWhen
|
a sink, optionally restricted by level, switch, or condition |
writeToLogger |
another logger, whose enrichers, filters, and sinks then apply |
writeToFallible, writeToFallbackChain, auditTo
|
failure handling of sinks |
enrichWith, enrichWithProperty, filterWith, filterExcluding, filterIncludingOnly
|
enrichment and filtering |
destructureByTransforming, destructureAsScalar, destructureWithRule, destructureByIgnoring, destructureByMasking
|
how structures are captured |
maximumDepth, maximumStringLength, maximumCollectionCount
|
capture limits |
selfLog, clock
|
where problems are reported and where time comes from |
createLogger, createReloadableLogger
|
the logger |
module Ex03Configuring
import Std.Io as Io
import PuduLangLog.Configuration as Configuration
import PuduLangLog.LevelSwitch as LevelSwitch
import PuduLangLog as Log
import PuduLangLog.Logger as Logger
import PuduLangLog.Sinks.Memory as Memory
import PuduLangLog.Value as Value
fn report(label: Str, memory: &Memory.Memory) -> () {
let _line = Io.writeLine(label + ": " + Memory.messages(memory).join(" | "))
}
export fn main() -> Int {
let everything = Memory.create()
let errors = Memory.create()
let audits = Memory.create()
let control = LevelSwitch.create(Log.Information)
LevelSwitch.onChange(&control, fn(before: Log.Level, after: Log.Level) -> () {
let _told = Io.writeLine("switch moved from " + show(before) + " to " + show(after))
})
let errorsOnly = Configuration.nested().filterIncludingOnly(fn(event: &Log.Event) -> Bool { event.level == Log.Error }).writeTo(Memory.sink(&errors)).createLogger()
let logger = Configuration.create()
.controlledBy(&control)
.overrideLevel("Shop.Http", Log.Warning)
.writeTo(Memory.sink(&everything))
.writeToLogger(&errorsOnly)
.writeToAtLeast(Memory.sink(&audits), Log.Warning)
.createLogger()
logger.debug("hidden until the switch moves", [])
logger.forSource("Shop.Http.Client").information("hidden by the override", [])
logger.forSource("Shop.Http.Client").warning("slow response", [])
LevelSwitch.set(&control, Log.Debug)
logger.debug("now visible", [])
logger.error("Order \{Id\} failed", [Value.int(9)])
report("everything", &everything)
report("errors only", &errors)
report("warning and above", &audits)
let early = Memory.create()
let bootstrap = Configuration.create().writeTo(Memory.sink(&early)).createReloadableLogger()
bootstrap.information("starting", [])
let later = Memory.create()
let _reloaded = Logger.reload(&bootstrap, Configuration.pipelineOf(&Configuration.create().writeTo(Memory.sink(&later))))
bootstrap.information("configured", [])
report("before reload", &early)
report("after reload", &later)
Logger.close(&logger)
Logger.close(&bootstrap)
0
}
Check it and run it:
pudu check src/Ex03Configuring.pudu
pudu run src/Ex03Configuring.puduOutput:
switch moved from Information to Debug
everything: slow response | now visible | Order 9 failed
errors only: Order 9 failed
warning and above: slow response | Order 9 failed
before reload: starting
after reload: configured
A level switch tells its listeners of each real change. createReloadableLogger builds a logger for startup; Logger.reload replaces its pipeline with the full configuration's, flushing and closing the previous one, and every logger derived from it follows.