2 unstable releases
0.2.0-beta.1 | Mar 3, 2024 |
---|---|
0.1.0 | Dec 9, 2022 |
#116 in Debugging
15,040 downloads per month
Used in 4 crates
(via tracing-capture)
79KB
1.5K
SLoC
Tunnelling Tracing Information Across API Boundary
This crate provides tracing infrastructure helpers allowing to transfer tracing events across an API boundary:
TracingEventSender
is a tracingSubscriber
that converts tracing events into (de)serializable presentation that can be sent elsewhere using a customizable hook.TracingEventReceiver
consumes events produced by aTracingEventSender
and relays them to the tracing infrastructure. It is assumed that the source of events may outlive both the lifetime of a particularTracingEventReceiver
instance, and the lifetime of the program encapsulating the receiver. To deal with this, the receiver provides the means to persist / restore its state.
This solves the problem of having dynamic call sites for tracing spans / events, i.e., ones not known during compilation. This may occur if call sites are defined in dynamically loaded modules the execution of which is embedded into the program, such as WASM modules.
See the crate docs for the details about the crate design and potential use cases.
Usage
Add this to your Crate.toml
:
[dependencies]
tracing-tunnel = "0.2.0-beta.1"
Note that the both pieces of functionality described above are gated behind opt-in features; consult the crate docs for details.
Sending tracing events
use std::sync::mpsc;
use tracing_tunnel::{TracingEvent, TracingEventSender, TracingEventReceiver};
// Let's collect tracing events using an MPSC channel.
let (events_sx, events_rx) = mpsc::sync_channel(10);
let subscriber = TracingEventSender::new(move |event| {
events_sx.send(event).ok();
});
tracing::subscriber::with_default(subscriber, || {
tracing::info_span!("test", num = 42_i64).in_scope(|| {
tracing::warn!("I feel disturbance in the Force...");
});
});
let events: Vec<TracingEvent> = events_rx.iter().collect();
println!("{events:?}");
// Do something with events...
Receiving tracing events
use std::sync::mpsc;
use tracing_tunnel::{
LocalSpans, PersistedMetadata, PersistedSpans, TracingEvent, TracingEventReceiver,
};
tracing_subscriber::fmt().pretty().init();
fn replay_events(events: &[TracingEvent]) {
let mut spans = PersistedSpans::default();
let mut local_spans = LocalSpans::default();
let mut receiver = TracingEventReceiver::default();
for event in events {
if let Err(err) = receiver.try_receive(event.clone()) {
tracing::warn!(%err, "received invalid tracing event");
}
}
// Persist the resulting receiver state. There are two pieces
// of the state: metadata and alive spans. The spans are further split
// into the persisted and local parts.
let metadata = receiver.persist_metadata();
let (spans, local_spans) = receiver.persist();
// Store `metadata` and `spans`, e.g., in a DB, and `local_spans`
// in a local data struct such as `HashMap` keyed by the executable ID.
}
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in tracing-toolbox
by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.
Dependencies
~0.5–1MB
~24K SLoC