1use std::io;
24use std::sync::Arc;
25use std::sync::Mutex;
26
27pub use ctor::ctor;
28use tracing_subscriber::fmt::format::FmtSpan;
29use tracing_subscriber::fmt::MakeWriter;
30use tracing_subscriber::fmt::Subscriber;
31use tracing_subscriber::EnvFilter;
32
33pub fn init() {
36 let builder = Subscriber::builder()
37 .with_env_filter(EnvFilter::from_env("LOG"))
38 .with_ansi(false)
39 .with_target(false)
40 .without_time()
41 .with_span_events(FmtSpan::ACTIVE);
42
43 builder.init();
44}
45
46pub fn traced(filter: &str, func: impl FnOnce()) -> Vec<String> {
49 #[derive(Clone, Default)]
50 struct Output(Arc<Mutex<Vec<String>>>);
51
52 impl MakeWriter<'_> for Output {
53 type Writer = Output;
54 fn make_writer(&self) -> Self::Writer {
55 self.clone()
56 }
57 }
58
59 impl io::Write for Output {
60 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
61 let mut lines = self.0.lock().unwrap();
62 let mut s = String::from_utf8_lossy(buf).trim().to_string();
63
64 if cfg!(fbcode_build) {
68 s = s.replace("_unittest: ", ": ");
69 s = s.replace("_unittest::", "::");
70 }
71
72 lines.push(s);
73 Ok(buf.len())
74 }
75 fn flush(&mut self) -> io::Result<()> {
76 Ok(())
77 }
78 }
79
80 let out = Output::default();
81 let builder = Subscriber::builder()
82 .with_env_filter(EnvFilter::new(filter))
83 .with_ansi(false)
84 .without_time()
85 .with_writer(out.clone())
86 .with_span_events(FmtSpan::ACTIVE);
87 let dispatcher = builder.finish();
88 tracing::subscriber::with_default(dispatcher, func);
89
90 let lines = out.0.lock().unwrap();
91 lines.clone()
92}
93
94#[macro_export]
96macro_rules! init {
97 () => {
98 #[dev_logger::ctor]
99 fn dev_logger_init_ctor() {
100 dev_logger::init();
101 }
102 };
103}
104
105#[test]
106fn test_traced() {
107 let lines = traced("info", || {
108 tracing::info_span!("bar", x = 1).in_scope(|| {
109 tracing::info!("foo");
110 tracing::debug!("foo2");
111 });
112 });
113 assert_eq!(
114 lines,
115 [
116 "INFO bar{x=1}: dev_logger: enter",
117 "INFO bar{x=1}: dev_logger: foo",
118 "INFO bar{x=1}: dev_logger: exit"
119 ]
120 );
121}