tracing_human_layer/
layer.rs1use std::fmt::Debug;
2use std::io::Stdout;
3use std::io::Write;
4use std::sync::atomic::AtomicBool;
5use std::sync::atomic::Ordering;
6
7use parking_lot::Mutex;
8use tracing::span;
9use tracing::Event;
10use tracing::Id;
11use tracing::Level;
12use tracing::Subscriber;
13use tracing_subscriber::fmt::format::FmtSpan;
14use tracing_subscriber::fmt::FormattedFields;
15use tracing_subscriber::layer::Context;
16use tracing_subscriber::registry::LookupSpan;
17use tracing_subscriber::registry::Scope;
18use tracing_subscriber::Layer;
19
20use crate::HumanEvent;
21use crate::HumanFields;
22use crate::Style;
23use crate::StyledSpanFields;
24
25pub struct HumanLayer<W = Stdout> {
27 last_event_was_long: AtomicBool,
36 span_events: FmtSpan,
38 color_output: bool,
40 output_writer: Mutex<W>,
42}
43
44impl<W> Debug for HumanLayer<W> {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 f.debug_struct("HumanLayer")
47 .field("color_output", &self.color_output)
48 .finish_non_exhaustive()
49 }
50}
51
52impl Default for HumanLayer {
53 fn default() -> Self {
54 Self {
55 last_event_was_long: Default::default(),
56 span_events: FmtSpan::NONE,
57 color_output: true,
58 output_writer: Mutex::new(std::io::stdout()),
59 }
60 }
61}
62
63impl HumanLayer {
64 pub fn new() -> Self {
66 Self::default()
67 }
68}
69
70impl<W> HumanLayer<W> {
71 pub fn with_output_writer<W2>(self, output_writer: W2) -> HumanLayer<W2> {
75 HumanLayer {
76 last_event_was_long: self.last_event_was_long,
77 span_events: self.span_events,
78 color_output: self.color_output,
79 output_writer: Mutex::new(output_writer),
80 }
81 }
82
83 pub fn with_color_output(mut self, color_output: bool) -> Self {
85 self.color_output = color_output;
86 self
87 }
88
89 pub fn with_span_events(mut self, span_events: FmtSpan) -> Self {
91 self.span_events = span_events;
92 self
93 }
94
95 fn update_long(&self, last_event_was_long: AtomicBool) {
96 self.last_event_was_long
97 .store(last_event_was_long.load(Ordering::SeqCst), Ordering::SeqCst);
98 }
99
100 fn event<S>(&self, level: Level, scope: Option<Scope<'_, S>>) -> HumanEvent
101 where
102 S: tracing::Subscriber,
103 S: for<'lookup> LookupSpan<'lookup>,
104 {
105 HumanEvent::new(
106 level,
107 self.last_event_was_long.load(Ordering::SeqCst).into(),
108 scope,
109 self.color_output,
110 )
111 }
112
113 fn event_for_id<S>(&self, id: &Id, ctx: Context<'_, S>) -> HumanEvent
114 where
115 S: tracing::Subscriber,
116 S: for<'lookup> LookupSpan<'lookup>,
117 {
118 self.event(
119 *ctx.metadata(id)
120 .expect("Metadata should exist for the span ID")
121 .level(),
122 ctx.span_scope(id),
123 )
124 }
125}
126
127impl<S, W> Layer<S> for HumanLayer<W>
128where
129 S: Subscriber,
130 S: for<'lookup> LookupSpan<'lookup>,
131 Self: 'static,
132 W: Write,
133{
134 fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
135 let mut fields = HumanFields::new_span();
136 attrs.record(&mut fields);
137 if let Some(span_ref) = ctx.span(id) {
138 span_ref
139 .extensions_mut()
140 .insert(FormattedFields::<HumanLayer>::new(
141 StyledSpanFields {
142 style: Style::new(*attrs.metadata().level(), self.color_output),
143 fields,
144 }
145 .to_string(),
146 ));
147
148 if self.span_events.clone() & FmtSpan::NEW != FmtSpan::NONE {
149 let mut human_event = self.event(*span_ref.metadata().level(), ctx.span_scope(id));
150 human_event.fields.message = Some("new".into());
151 let _ = write!(self.output_writer.lock(), "{human_event}");
152 self.update_long(human_event.last_event_was_long);
153 }
154 }
155 }
156
157 fn on_record(&self, id: &Id, values: &span::Record<'_>, ctx: Context<'_, S>) {
158 let mut fields = HumanFields::new_span();
159 values.record(&mut fields);
160 if let Some(span_ref) = ctx.span(id) {
161 span_ref
162 .extensions_mut()
163 .insert(FormattedFields::<HumanLayer>::new(
164 StyledSpanFields {
165 style: Style::new(*span_ref.metadata().level(), self.color_output),
166 fields,
167 }
168 .to_string(),
169 ));
170 }
171 }
172
173 fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
174 let mut human_event = self.event(*event.metadata().level(), ctx.event_scope(event));
175 event.record(&mut human_event);
176 let _ = write!(self.output_writer.lock(), "{human_event}");
177 self.update_long(human_event.last_event_was_long);
178 }
179
180 fn on_enter(&self, id: &Id, ctx: Context<'_, S>) {
181 if self.span_events.clone() & FmtSpan::ENTER != FmtSpan::NONE {
182 let mut human_event = self.event_for_id(id, ctx);
183 human_event.fields.message = Some("enter".into());
184 let _ = write!(self.output_writer.lock(), "{human_event}");
185 self.update_long(human_event.last_event_was_long);
186 }
187 }
188
189 fn on_exit(&self, id: &Id, ctx: Context<'_, S>) {
190 if self.span_events.clone() & FmtSpan::EXIT != FmtSpan::NONE {
191 let mut human_event = self.event_for_id(id, ctx);
192 human_event.fields.message = Some("exit".into());
193 let _ = write!(self.output_writer.lock(), "{human_event}");
194 self.update_long(human_event.last_event_was_long);
195 }
196 }
197
198 fn on_close(&self, id: Id, ctx: Context<'_, S>) {
199 if self.span_events.clone() & FmtSpan::CLOSE != FmtSpan::NONE {
200 let mut human_event = self.event_for_id(&id, ctx);
201 human_event.fields.message = Some("close".into());
202 let _ = write!(self.output_writer.lock(), "{human_event}");
203 self.update_long(human_event.last_event_was_long);
204 }
205 }
206}