1use parking_lot::Mutex;
7use std::sync::Arc;
8use tracing_subscriber::filter::Targets;
9use tracing_subscriber::fmt::format::FmtSpan;
10use tracing_subscriber::layer::SubscriberExt;
11use tracing_subscriber::util::SubscriberInitExt;
12
13static TRACING_WRITER: Mutex<Option<Arc<TracingWriter>>> = Mutex::new(None);
16
17pub fn init_tracing() -> mesh::pipe::ReadPipe {
23 let (log_read, log_write) = mesh::pipe::pipe();
24
25 let mut global = TRACING_WRITER.lock();
26 if let Some(writer) = global.as_ref() {
27 *writer.0.lock() = log_write;
30 } else {
31 let writer = Arc::new(TracingWriter(Mutex::new(log_write)));
32 *global = Some(writer.clone());
33 drop(global);
34
35 let targets = Targets::new()
36 .with_default(tracing::level_filters::LevelFilter::DEBUG)
37 .with_target("mesh_remote", tracing::level_filters::LevelFilter::INFO);
38
39 tracing_subscriber::fmt()
40 .compact()
41 .with_ansi(false)
42 .with_timer(tracing_subscriber::fmt::time::uptime())
43 .with_writer(writer)
44 .with_max_level(tracing::level_filters::LevelFilter::DEBUG)
45 .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
46 .log_internal_errors(true)
47 .finish()
48 .with(targets)
49 .init();
50 }
51
52 tracing::info!("tracing initialized");
53 log_read
54}
55
56struct TracingWriter(Mutex<mesh::pipe::WritePipe>);
57
58impl std::io::Write for &TracingWriter {
59 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
60 self.0.lock().write_nonblocking(buf)
63 }
64
65 fn flush(&mut self) -> std::io::Result<()> {
66 Ok(())
67 }
68}