Expand description
§tracing-wide
[!CAUTION] This is NOT an official tokio / tokio-tracing product or associated crate.
This crate enables wide events for tokio tracing. It enables additional functionality for tracing but does not implement / replace it.
Wide events are built as one struct per event, carrying every observability-relevant field for that event. The message text of such an event stays static; all variance lives in typed fields.
The core of the crate is no_std and runs in WASM.
Highlights include:
- Typed wide events: one struct per event via
#[message];event!checks required fields, fills unsetOptions from the ambient span, fans out to subscribers, then records totracingat the type’s level. - Flexible serialization: none,
serde, orfacet; opt-in per type, never a bound onMessage. - Catalogue: every message a binary can emit, auto-registered and walkable,
including messages defined in libraries or member crates as long as they’re
linked in. The catalogue is representation-agnostic - it’s plain data you can
serialize to any format (or none): a manifest (
msgis the unique join key) that non-technical stakeholders can reason about, with duplicate keys detectable in a test. - Automatic origin: crate / module / file / line / column captured per message, object-safe and drift-free.
- Ambient autocapture:
Optionfields fill at emit time from same-named fields on the surroundingtracing::instrumentspan, across crate boundaries. - Subscribers: each event reaches registered sinks as a typed
&dyn Messagebefore thetracinghandoff; stay generic via accessors or downcast. - Routing: on static
tags()with no downcast, or (withfacet) on live field values read by name.
§Getting started
use tracing_wide::{event, message};
// One struct per event: the message text is static, the fields carry the variance.
#[message(msg = "hello world")]
struct Hello {
who: &'static str,
}
// Emit it: builds the struct and records it to `tracing` at the type's level.
event!(Hello { who: "world" });§Examples
catalogue-facet: dump the catalogue as YAML viafacet-yamlcatalogue-serde: dump the catalogue as YAML viaserdeinstrument: fillOptionfields from surrounding spanssubscriber-facet: filter on a live field value viaas_facetsubscriber-serde: forward each event as JSON viaas_serializesubscriber: a generic line printer plus a typed downcasting sinktags: route messages by tag with no downcast
§Feature flags
-
docs— Documentation-only: pulls in every dependency and rendering needed to build the full rustdoc (currentlydocument-features, which renders this list). Enabled by docs.rs andjust docs; never needed by applications or libraries. -
catalogue— Auto-collected per-type catalogue: inventory registration + descriptors. On its own the descriptors are plain data; addserdeand they gainSerialize.Tooling-only feature. Should neither be enabled for applications nor libraries.
-
facet— Facet reflection integration. Theas_facethook onMessagehands a subscriber afacet::Peekover a live message body — enabled per type by#[derive(Facet)]alone — for introspection: pull fields out by name and filter on an individual field, not just on tags. Distinct fromserde, which forwards the body whole; this pulls it apart.Unstable: facet is pre-1.0 and every minor is a breaking change, so this feature tracks that churn — expect breakage. facet is re-exported as
tracing_wide::facetso a subscriber namesPeek/Facet/the derive through one coherent version. -
instrument— Instrument integration (ambient autocapture): a tracing-subscriberLayerthat captures span field values — i.e. whattracing::instrumentrecords — and an emit-time join that fills a message’s still-NoneOptionfields by name from the current span scope. OnlyOptionfields join; a miss is legal (None). Requires the app’s subscriber to be built ontracing_subscriber::registry()withinstrument::layer()installed — without them,event!degrades gracefully (fields stayNone).Application-only feature. Should only be enabled for applications, not for libraries.
-
serde— Serde integration. On its own: the erased-serde hook onMessage(as_serialize) that lets a subscriber serialize a live message body without naming its concrete type — enabled per type by#[derive(Serialize)]alone. Combined withcatalogue, the catalogue descriptors also deriveSerialize(for dumping to JSON/TOML). -
std(enabled by default) — Opt-in std - required for all features beyond core functionality. -
subscriber— Global subscriber registry + typed&dyn Messagefan-out that runs before the tracing handoff. Without it,event!just records to tracing.Application-only feature. Should only be enabled for applications, not for libraries.
Re-exports§
pub use ::facet;
Modules§
- catalogue
- The auto-collected catalogue: per-type descriptors registered by
#[message]and read back at runtime. Gated as a whole by thecataloguefeature. - examples
- Examples
- instrument
- Ambient autocapture: fill a message’s
Optionfields from the tracing span scope at emit time. Gated by theinstrumentfeature. - subscriber
- App-level subscriber mechanics: a global registry whose handlers see each
emitted message as a typed
&dyn Messagebefore the tracing handoff. Gated by thesubscriberfeature — without it,event!just records to tracing and the core stays free of global state.
Macros§
- event
- Function-like macro: construct a
Messageand record it.
Structs§
- Origin
- Where a message type is defined — automatic provenance captured by
#[message], which emits thecorelocation builtins (env!("CARGO_PKG_NAME"),module_path!,file!,line!,column!) for rustc to fill while compiling the defining crate.
Traits§
- Field
- Marker trait: a type eligible to be a field of a message.
- Message
- A struct that may be emitted as a wide event.
Attribute Macros§
- message
- Attribute macro: mark a struct as a
Message.