Skip to main content

Module logging

Module logging 

Source
Expand description

[logging] — resolving the configuration into an installed subscriber, and swapping it on a reload.

The rule the whole module follows: every knob is validated before anything is installed, and an unknown value is an error the caller prints and exits on rather than a silent fallback. A certificate authority running at a log level or to a destination its operator did not ask for is worse than one that refuses to start and says why.

Which invocation gets a subscriber at all, and the --log-level flag whose directive outranks RUST_LOG and logging.filter, are the CLI’s (cli::logging); this module takes that directive as a string and records which of the three layers won in [FilterSource], so a reload can say.

§Reloading

All six keys reload on SIGHUP, which is why the whole stack is built as one [Installed] layer behind a tracing_subscriber::reload::Layer rather than through the tracing_subscriber::fmt() builder. Three things that shape rests on, each a bug if reversed:

  • The filter is composed with Layer::and_then, never with_filter. reload::Handle::reload is documented as unusable with a tracing_subscriber::filter::Filtered layer (tokio-rs/tracing#1629), because replacing it mints a filter id the registry never saw. and_then is global filtering — Layered::enabled is the conjunction of both halves — which is exactly the semantics with_env_filter gave before.
  • One boxed layer, not two. Box<dyn Layer<S>> has to name its S, and a second .with() makes the next layer’s S the Layered<…> of the first — a type nothing can write down in a static. One box is also one lock rather than two.
  • The handle lives in a process-wide OnceLock, beside the global it is a handle to. The subscriber already is process-global (.init() panics on a second call); this is not a second one. Threading the handle from main.rs to server::generation::publish_reload instead would touch six signatures, including the serve_on* seams every test enters through. When it is unset — a test binary, or a consumer that installed its own subscriber — [publish_logging] is a no-op that says so, since logging is then not ours to swap.

The cost, stated rather than buried: a reload::Layer puts an RwLock read on every event.

Functions§

init_command_logging
Installs the diagnostic subscriber a one-shot admin command asked for.
init_logging
Installs the process-wide tracing subscriber from [logging].