tracing_perfspan/
lib.rs

1use probe::probe;
2use tracing::{level_filters::LevelFilter, span, Subscriber};
3use tracing_subscriber::{
4    layer::{Context, SubscriberExt},
5    registry::LookupSpan,
6    Layer,
7};
8
9/// Initialize tracing with PerfspanLayer.
10///
11/// Uses DEBUG as the default level for spans, but can be overridden by setting
12/// the PERF_SPAN_LEVEL environment variable.
13pub fn init() {
14    let env_filter = tracing_subscriber::EnvFilter::builder()
15        .with_default_directive(LevelFilter::DEBUG.into())
16        .with_env_var("PERF_SPAN_LEVEL")
17        .from_env_lossy();
18    let layer = PerfspanLayer {}.with_filter(env_filter);
19    let subscriber = tracing_subscriber::Registry::default().with(layer);
20    tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
21}
22
23pub struct PerfspanLayer {}
24
25impl<S> Layer<S> for PerfspanLayer
26where
27    S: Subscriber + for<'span> LookupSpan<'span>,
28{
29    fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
30        if let Some(span) = ctx.span(id) {
31            let name_size = span.name().len() as u16;
32            let name = span.name().as_ptr();
33            let span_id = span.id().into_u64();
34            probe!(perfspan, enter, span_id, name_size, name);
35        }
36    }
37
38    fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
39        if let Some(span) = ctx.span(id) {
40            let name_size = span.name().len() as u16;
41            let name = span.name().as_ptr();
42            let span_id = span.id().into_u64();
43            probe!(perfspan, exit, span_id, name_size, name);
44        }
45    }
46}