1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
crate::ix!();

pub struct BufferedLayer {
    pub(crate) tag:    Option<String>,
    pub(crate) buffer: Arc<Mutex<Vec<String>>>,
}

impl Clone for BufferedLayer {

    fn clone(&self) -> Self {
        Self {
            tag:    self.tag.clone(),
            buffer: Arc::clone(&self.buffer),
        }
    }
}

impl BufferedLayer {

    pub fn new(tag: &str) -> Self {
        Self {
            tag:    Some(tag.to_string()),
            buffer: Arc::new(Mutex::new(Vec::new())),
        }
    }
}

impl Default for BufferedLayer {

    fn default() -> Self {
        Self {
            tag:    None,
            buffer: Arc::new(Mutex::new(Vec::new())),
        }
    }
}

impl<S: Subscriber> tracing_subscriber::Layer<S> for BufferedLayer {

    fn on_event(&self, event: &tracing::Event<'_>, _ctx: Context<'_, S>) {

        use std::fmt::Write;

        pub enum EventPrintType {
            FullWithHeader,
            LogLineAndContents,
            JustTheContents,
        }

        if let Ok(mut buf) = self.buffer.lock() {

            match EventPrintType::JustTheContents {

                EventPrintType::FullWithHeader => {

                    // Capture the event's formatted representation
                    // and store it in the buffer
                    //
                    let mut message = String::new();

                    let _ = write!(&mut message, "{:#?}", event); 

                    buf.push(message);

                },
                EventPrintType::LogLineAndContents => {

                    let metadata = event.metadata();

                    let mut message = format!("[{}] {}: ", metadata.level(), metadata.target());

                    // Visitor to collect fields
                    struct FieldCollector(String);

                    impl tracing::field::Visit for FieldCollector {
                        fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
                            use std::fmt::Write;
                            let _ = write!(self.0, "{} = {:?}, ", field.name(), value);
                        }
                    }

                    let mut visitor = FieldCollector(String::new());

                    event.record(&mut visitor);

                    if !visitor.0.is_empty() {
                        // Trim trailing comma and space
                        message.push_str(&visitor.0[..visitor.0.len() - 2]);
                    }

                    buf.push(message);
                },
                EventPrintType::JustTheContents => {

                    let metadata = event.metadata();

                    //let mut message = format!("[{}] {}: ", metadata.level(), metadata.target());
                    let mut message = format!("");

                    // Visitor to collect fields
                    struct FieldCollector(String);

                    impl tracing::field::Visit for FieldCollector {
                        fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
                            use std::fmt::Write;
                            //let _ = write!(self.0, "{} = {:?}, ", field.name(), value);
                            let _ = write!(self.0, "{:?}, ", value);
                        }
                    }

                    let mut visitor = FieldCollector(String::new());

                    event.record(&mut visitor);

                    if !visitor.0.is_empty() {
                        // Trim trailing comma and space
                        message.push_str(&visitor.0[..visitor.0.len() - 2]);
                    }

                    buf.push(message);
                }
            }
        }
    }
}