tracing_rerun/
lib.rs

1use rerun::{RecordingStream, TextLogLevel};
2use tracing::{Event, Level, Subscriber};
3use tracing_subscriber::{layer::Context, Layer};
4
5fn to_rerun_log_level(tracing_level: &Level) -> TextLogLevel {
6    match *tracing_level {
7        Level::ERROR => TextLogLevel::ERROR.into(),
8        Level::WARN => TextLogLevel::WARN.into(),
9        Level::INFO => TextLogLevel::INFO.into(),
10        Level::DEBUG => TextLogLevel::DEBUG.into(),
11        Level::TRACE => TextLogLevel::TRACE.into(),
12    }
13}
14
15/// Send every tracing event to Rerun as a TextLog.
16pub struct RerunLayer {
17    pub rec: RecordingStream,
18    pub path: String, // e.g. "logs/tracing"
19}
20
21impl<S> Layer<S> for RerunLayer
22where
23    S: Subscriber + for<'lookup> tracing_subscriber::registry::LookupSpan<'lookup>,
24{
25    fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
26        use std::fmt::Write;
27        // Collect span stack (innermost -> root)
28        let spans = ctx
29            .lookup_current()
30            .map(|s| {
31                s.scope()
32                    .map(|s| s.metadata().name().to_string())
33                    .collect::<Vec<_>>()
34                    .join("::")
35            })
36            .unwrap_or_default();
37
38        // Collect fields
39        struct Visitor<'a> { buf: &'a mut String }
40        impl<'a> tracing::field::Visit for Visitor<'a> {
41            fn record_debug(
42                &mut self,
43                _field: &tracing::field::Field,
44                value: &dyn std::fmt::Debug
45            ) {
46                let _ = write!(self.buf, "{:?} ", value);
47            }
48        }
49
50        let meta = event.metadata();
51        let mut msg = String::new();
52        let span_prefix = if spans.is_empty() { 
53            String::new() 
54        } else { 
55            format!("{spans}: ") 
56        };
57        let _ = write!(
58            msg,
59            "{}{}: ",
60            span_prefix,
61            meta.target()
62        );
63        let mut v = Visitor { buf: &mut msg };
64        event.record(&mut v);
65
66        // Ship to Rerun
67        let text = rerun::archetypes::TextLog::new(msg).with_level(to_rerun_log_level(meta.level()));
68        let _ = self.rec.log(self.path.as_str(), &text);
69    }
70}