tracing_setup/
buffered_layer.rs

1crate::ix!();
2
3#[derive(Getters, Setters, Debug)]
4#[getset(get = "pub", set = "pub")]
5pub struct BufferedLayer {
6    tag: Option<String>,
7    buffer: Arc<Mutex<Vec<String>>>,
8
9    /// The single source of truth for how we print events:
10    event_printer: EventPrinter,
11}
12
13impl BufferedLayer {
14    pub fn new_with_tag(tag: &str) -> Self {
15        Self {
16            tag: Some(tag.to_string()),
17            buffer: Arc::new(Mutex::new(Vec::new())),
18            event_printer: EventPrinter::default(),
19        }
20    }
21}
22
23// A single, unified impl Layer<S>
24impl<S: Subscriber> tracing_subscriber::Layer<S> for BufferedLayer {
25
26    fn on_event(&self, event: &tracing::Event<'_>, _ctx: Context<'_, S>) {
27        if let Ok(mut buf) = self.buffer.lock() {
28
29            match &self.event_printer {
30                EventPrinter::FullWithHeader => {
31                    // Original approach: debug-print the entire event
32                    let mut msg = String::new();
33                    let _ = write!(&mut msg, "{:#?}", event);
34                    buf.push(msg);
35                }
36
37                EventPrinter::LogLineAndContents {
38                    show_timestamp,
39                    show_loglevel,
40                } => {
41                    // Single-line approach with optional timestamp/level
42                    use chrono::{Local, SecondsFormat};
43                    let now  = Local::now().to_rfc3339_opts(SecondsFormat::Millis, true);
44                    let meta = event.metadata();
45
46                    let mut line = String::new();
47
48                    if *show_timestamp {
49                        line.push_str(&now);
50                        line.push(' ');
51                    }
52                    if *show_loglevel {
53                        line.push('[');
54                        line.push_str(&meta.level().to_string());
55                        line.push(' ');
56                        line.push_str(meta.target());
57                        line.push_str("] ");
58                    }
59
60                    // Collect field data
61                    struct FieldCollector(String);
62                    impl tracing::field::Visit for FieldCollector {
63                        fn record_debug(&mut self, f: &tracing::field::Field, v: &dyn std::fmt::Debug) {
64                            let _ = write!(self.0, "{} = {:?}, ", f.name(), v);
65                        }
66                    }
67                    let mut visitor = FieldCollector(String::new());
68                    event.record(&mut visitor);
69
70                    if !visitor.0.is_empty() {
71                        // Remove trailing ", "
72                        visitor.0.truncate(visitor.0.len().saturating_sub(2));
73                        line.push_str(&visitor.0);
74                    }
75
76                    buf.push(line);
77                }
78
79                EventPrinter::JustTheContents => {
80                    // Minimal approach: only the field values
81                    let mut message = String::new();
82                    struct FieldCollector(String);
83                    impl tracing::field::Visit for FieldCollector {
84                        fn record_debug(&mut self, _f: &tracing::field::Field, v: &dyn std::fmt::Debug) {
85                            let _ = write!(self.0, "{:?}, ", v);
86                        }
87                    }
88                    let mut visitor = FieldCollector(String::new());
89                    event.record(&mut visitor);
90
91                    if !visitor.0.is_empty() {
92                        visitor.0.truncate(visitor.0.len().saturating_sub(2));
93                        message.push_str(&visitor.0);
94                    }
95
96                    buf.push(message);
97                }
98            }
99        }
100    }
101}
102
103// The flush logic remains as-is (unchanged):
104impl Flushable for BufferedLayer {
105    fn flush(&self) {
106        use colored::Colorize;
107
108        if let Ok(mut buf) = self.buffer.lock() {
109            if let Some(tag) = &self.tag {
110                let msg = format!("---------------------------------------------------------[trace_events: {}]", tag);
111                println!("{}", msg.bright_blue());
112            }
113
114            for message in &*buf {
115                println!("{}", message);
116            }
117            buf.clear();
118        }
119    }
120}
121
122impl Clone for BufferedLayer {
123
124    fn clone(&self) -> Self {
125        Self {
126            tag:            self.tag.clone(),
127            buffer:         Arc::clone(&self.buffer),
128            event_printer:  self.event_printer.clone(),
129        }
130    }
131}
132
133impl Default for BufferedLayer {
134
135    fn default() -> Self {
136        Self {
137            tag:           None,
138            buffer:        Arc::new(Mutex::new(Vec::new())),
139            event_printer: EventPrinter::default(),
140        }
141    }
142}