Expand description
A tiny logging facade that forwards to defmt, tracing, both, or
neither, chosen by Cargo features.
Consortium spans no_std firmware (which logs with defmt) and std
host-side tooling such as the config codegen (which logs with tracing).
This crate lets a single call site — consortium_log::trace!(...) — compile
against whichever backend the consuming crate turns on:
defmtroutes each macro to the matchingdefmtmacro.tracingroutes each macro to the matchingtracingmacro.tracingalso enablesallocbecause thetracingdependency needs it.- With both enabled, every event is emitted to both backends.
- With neither enabled, the macros expand to nothing.
§Format syntax
The portable subset is a format string plus positional arguments —
trace!("channel {} lowered", name) — or Rust-style implicit captures —
trace!("channel {name} lowered"). Implicit captures are normalized to
indexed arguments before being forwarded, because defmt does not parse
them itself. Each argument must implement the traits both backends require
(defmt::Format for defmt, core::fmt::Display/Debug for tracing).
Backend-specific extensions (defmt’s {=u8} type hints, tracing’s
structured fields) are only valid when that backend is the sole one enabled.
Log arguments must be side-effect free: when no backend is enabled the macros expand to nothing and the arguments are never evaluated.
§Features
defmt— forward to thedefmtlogging macros. No directdefmtdependency is needed at the call site: this crate re-exportsdefmt(the re-export exists only when the feature is on, so it is not linked here) and the dispatch macro binds it into scope for the expansion.tracing— forward to thetracinglogging macros (impliesalloc).tracing’s macros are$crate-hygienic, so no direct dependency is needed beyond this crate.alloc— marker capability required bytracing; enabling it alone pulls no backend.
Neither backend leaks its name into the call site, so enabling one on this
crate alone resolves. That matters under Cargo feature unification: one
workspace member turning on consortium-log/defmt switches the facade for
every member sharing the build, including ones whose own defmt feature
is off and which therefore have no defmt in their extern prelude.
Names are only half of it, though. With the defmt backend live, every
logged argument needs a defmt::Format impl, and a crate that gates its
impls on its own defmt feature will not have emitted them — foreign
types such as anyhow::Error cannot have them at all. Gate those impls with
when_defmt! so they track the backend, and, for the types
that can never implement it, keep consortium-log/defmt out of any default
feature so a host build never switches the backend on by accident.
Macros§
- debug
- Logs at the
debuglevel to every enabled backend. - error
- Logs at the
errorlevel to every enabled backend. - info
- Logs at the
infolevel to every enabled backend. - trace
- Logs at the
tracelevel to every enabled backend. See the crate docs for the portable format syntax. - warn
- Logs at the
warnlevel to every enabled backend. - when_
defmt - Drops the items it wraps, because this crate’s
defmtbackend is disabled.