Module log
Structured logging — level-filtered, optionally timestamped and
target-tagged, thread-safe, with a free-function facade
(plans/archive/STD_API_AUDIT.md §7 log row: the zero-user rewrite window).
log :: import "std/log";
log.set_level(log.Level.Debug);
log.info(`server started on ${port}`); // any ToString value
log.info_lazy(() => expensive_summary()); // String, built only if it passes
log.set_timestamps(true);
log.warn_target(`db`, `slow query: ${ms}ms`); // "[WARN ] [db] ..."
The level filter runs BEFORE the message is rendered — the plain forms
still evaluate their argument at the call site (the value already
exists), but the *_lazy forms take a () -> String closure CALLED ONLY when
the message will actually be emitted. A single mutex serializes the
filter check and the write, so lines from different OS threads never
interleave (the parallelism runtime is the multi-threaded path; the async
runtime is single-threaded and never contends).
Choosing a level follows Rust's log crate: Error for a failure the
program could not handle, Warn for a hazard it recovered from, Info
for the handful of lines an operator wants, Debug for developer detail,
Trace for per-step verbosity. The default filter is Info, so Debug
and Trace produce nothing until set_level or YO_LOG lowers it.
Stability
unstable — one name is a known convention violation and one piece of the record shape is missing.
get_level carries a get_ prefix that D2 rules out (Rust would spell it
level()); it is listed among the D2 violations in
plans/STD_API_STABILIZATION.md §1 and renaming it is breaking, so it has
not happened yet. The Sink trait and YO_LOG are themselves one release
old (#494).
Three gaps against Rust's log, each of which would change a signature
here: there is no Record — a sink gets (level, target, msg) and cannot
learn the file, line or module a line came from, because target is
caller-supplied text rather than metadata; YO_LOG takes a bare level
where env_logger takes per-target directives (RUST_LOG=mymod=debug),
which is the filtering everyone actually wants; and set_sink is
re-settable at any time, where Rust's set_logger is set-once and returns
a Result, so here a library can silently steal the application's sink.
Freezing follows those decisions.
Types
Log severity, ascending. Off disables all output — filtering against it
drops every message, including Error.
Variants
| Variant | Fields | Description |
|---|---|---|
Trace | ||
Debug | ||
Info | ||
Warn | ||
Error | ||
Off |
Trait Implementations
impl(generic(T : Type), where(T <: ToString), T : (ToString))
impl(generic(T : Type), where(T <: ToString), T : (ToString), Format)
format : fn(self : Self, spec : str) -> StringRender self under spec. An unrecognised spec degrades to the plain
to_string() rendering rather than failing.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Self | |
spec | str |
Returns: String
impl(Level, ToString(...))
to_string : (Level) fn(self : Level) -> Stringimpl(Level, Eq(Level))
Where log lines are written.
Variants
| Variant | Fields | Description |
|---|---|---|
Stderr | ||
Stdout |
Traits / Modules
A pluggable log destination — implement it to send records somewhere other than stdout/stderr (a file, a ring buffer, a test recorder, a network collector).
write_line receives the record's PARTS, not a formatted line, so a sink
is free to render its own format — JSON, say — instead of re-parsing ours.
target is empty when the caller used the untargeted forms.
It is called with the module's mutex HELD, which is what keeps concurrent lines from interleaving. A sink must therefore not log, directly or indirectly: that would deadlock.
Methods
Functions
Parse a level name, case-insensitively — trace, debug, info, warn,
error, off. .None for anything else.
warning is accepted for warn because it is the spelling people reach
for, and rejecting it silently would be the worst of the three options.
Parameters
| Name | Type | Notes |
|---|---|---|
name | String |
Send every record to sink instead of stdout/stderr.
set_output and set_timestamps stop having any effect while a sink is
installed — rendering is the sink's job. The LEVEL filter still applies, so
a sink never sees a record the configuration suppressed.
Parameters
| Name | Type | Notes |
|---|---|---|
sink | Dyn(Sink) |
Returns: unit
Go back to writing to stdout/stderr.
Returns: unit
Apply YO_LOG to the level filter, if it is set to a name
level_from_string recognises. Returns the level in force afterwards.
Explicit, not automatic, for the same reason Rust's env_logger::init()
is: a library that silently reconfigured logging on first use would be
impossible to reason about. Call it once at startup.
An unset or unrecognised YO_LOG leaves the current level alone — a typo
must not silence a program.
Returns: Level
Set the minimum level that is emitted (Off silences everything). The
default, before any call to this, is Info.
Parameters
| Name | Type | Notes |
|---|---|---|
level | Level |
Returns: unit
Choose stdout or stderr (default stderr).
Parameters
| Name | Type | Notes |
|---|---|---|
output | LogOutput |
Returns: unit
Prefix each line with an RFC 3339 UTC timestamp when true.
Parameters
| Name | Type | Notes |
|---|---|---|
on | bool |
Returns: unit
True iff a message at level would be emitted right now — the guard the
lazy forms check before building their message.
Parameters
| Name | Type | Notes |
|---|---|---|
level | Level |
Returns: bool
Log a ToString value at level.
Type Parameters
| Name | Type | Notes |
|---|---|---|
T | Type | comptime |
Parameters
| Name | Type | Notes |
|---|---|---|
level | Level | |
msg | T |
Returns: unit
Log a ToString value at level, tagged with a target/module string.
Type Parameters
| Name | Type | Notes |
|---|---|---|
T | Type | comptime |
Parameters
| Name | Type | Notes |
|---|---|---|
level | Level | |
target | str | |
msg | T |
Returns: unit
Per-step verbosity at Trace — Rust's trace!. Silent under the default
Info filter.
Type Parameters
| Name | Type | Notes |
|---|---|---|
T | Type | comptime |
Parameters
| Name | Type | Notes |
|---|---|---|
msg | T |
Returns: unit
Developer detail at Debug — Rust's debug!. Also silent under the
default Info filter.
Type Parameters
| Name | Type | Notes |
|---|---|---|
T | Type | comptime |
Parameters
| Name | Type | Notes |
|---|---|---|
msg | T |
Returns: unit
A line an operator should see, at Info — Rust's info!. This is the
lowest level the default filter admits.
Type Parameters
| Name | Type | Notes |
|---|---|---|
T | Type | comptime |
Parameters
| Name | Type | Notes |
|---|---|---|
msg | T |
Returns: unit
A hazard the program recovered from, at Warn — Rust's warn!.
Type Parameters
| Name | Type | Notes |
|---|---|---|
T | Type | comptime |
Parameters
| Name | Type | Notes |
|---|---|---|
msg | T |
Returns: unit
A failure, at Error — Rust's error!. The highest level, but still
suppressed by Level.Off, which drops everything.
Type Parameters
| Name | Type | Notes |
|---|---|---|
T | Type | comptime |
Parameters
| Name | Type | Notes |
|---|---|---|
msg | T |
Returns: unit
trace tagged with a subsystem name, which renders as [db] between the
level and the message and reaches a Sink as its own argument — Rust's
trace!(target: "db", ...).
The tag is caller-supplied text; nothing derives or checks it, and it does not participate in filtering (the level is the only filter).
Type Parameters
| Name | Type | Notes |
|---|---|---|
T | Type | comptime |
Parameters
| Name | Type | Notes |
|---|---|---|
target | str | |
msg | T |
Returns: unit
debug with a subsystem tag; see trace_target.
Type Parameters
| Name | Type | Notes |
|---|---|---|
T | Type | comptime |
Parameters
| Name | Type | Notes |
|---|---|---|
target | str | |
msg | T |
Returns: unit
info with a subsystem tag; see trace_target.
Type Parameters
| Name | Type | Notes |
|---|---|---|
T | Type | comptime |
Parameters
| Name | Type | Notes |
|---|---|---|
target | str | |
msg | T |
Returns: unit
warn with a subsystem tag; see trace_target.
Type Parameters
| Name | Type | Notes |
|---|---|---|
T | Type | comptime |
Parameters
| Name | Type | Notes |
|---|---|---|
target | str | |
msg | T |
Returns: unit
error with a subsystem tag; see trace_target.
Type Parameters
| Name | Type | Notes |
|---|---|---|
T | Type | comptime |
Parameters
| Name | Type | Notes |
|---|---|---|
target | str | |
msg | T |
Returns: unit
trace, with the message built by make ONLY if Trace passes the
filter — the form to use when rendering costs real work (a formatted dump,
a query plan). The plain forms cannot help there: their argument is
evaluated at the call site whatever the filter says.
Untagged; there is no lazy *_target form.
Parameters
| Name | Type | Notes |
|---|---|---|
make | Impl(Fn() -> String) |
Returns: unit
debug with the message built only if Debug passes the filter; see
trace_lazy.
Parameters
| Name | Type | Notes |
|---|---|---|
make | Impl(Fn() -> String) |
Returns: unit
info with the message built only if Info passes the filter; see
trace_lazy.
Parameters
| Name | Type | Notes |
|---|---|---|
make | Impl(Fn() -> String) |
Returns: unit
warn with the message built only if Warn passes the filter; see
trace_lazy.
Parameters
| Name | Type | Notes |
|---|---|---|
make | Impl(Fn() -> String) |
Returns: unit
error with the message built only if Error passes the filter; see
trace_lazy.
Parameters
| Name | Type | Notes |
|---|---|---|
make | Impl(Fn() -> String) |
Returns: unit