1pub(crate) mod format;
2
3use format::{Buffers, ColorLevel, Config, FmtEvent, SpanMode};
4use nu_ansi_term::{Color, Style};
5use std::{
6 fmt::{self, Write as _},
7 io,
8 sync::Mutex,
9 time::Instant,
10};
11use tracing_core::{
12 field::{Field, Visit},
13 span::{Attributes, Id},
14 Event, Subscriber,
15};
16#[cfg(feature = "tracing-log")]
17use tracing_log::NormalizeEvent;
18use tracing_subscriber::{
19 fmt::MakeWriter,
20 layer::{Context, Layer},
21 registry::{self, LookupSpan},
22};
23
24pub(crate) struct Data {
25 start: Instant,
26 kvs: Vec<(&'static str, String)>,
27}
28
29impl Data {
30 pub fn new(attrs: &Attributes<'_>) -> Self {
31 let mut span = Self {
32 start: Instant::now(),
33 kvs: Vec::new(),
34 };
35 attrs.record(&mut span);
36 span
37 }
38}
39
40impl Visit for Data {
41 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
42 self.kvs.push((field.name(), format!("{value:?}")))
43 }
44}
45#[derive(Debug)]
46pub struct HierarchicalLayer<W = fn() -> io::Stderr>
47where
48 W: for<'writer> MakeWriter<'writer> + 'static,
49{
50 make_writer: W,
51 bufs: Mutex<Buffers>,
52 config: Config,
53}
54
55impl Default for HierarchicalLayer {
56 fn default() -> Self {
57 Self::new(2)
58 }
59}
60
61impl HierarchicalLayer<fn() -> io::Stderr> {
62 pub fn new(indent_amount: usize) -> Self {
63 let ansi = atty::is(atty::Stream::Stderr);
64 let config = Config {
65 ansi,
66 indent_amount,
67 ..Default::default()
68 };
69 Self {
70 make_writer: io::stderr,
71 bufs: Mutex::new(Buffers::new()),
72 config,
73 }
74 }
75}
76
77impl<W> HierarchicalLayer<W>
78where
79 W: for<'writer> MakeWriter<'writer> + 'static,
80{
81 pub fn with_ansi(self, ansi: bool) -> Self {
83 Self {
84 config: self.config.with_ansi(ansi),
85 ..self
86 }
87 }
88
89 pub fn with_writer<W2>(self, make_writer: W2) -> HierarchicalLayer<W2>
90 where
91 W2: for<'writer> MakeWriter<'writer>,
92 {
93 HierarchicalLayer {
94 make_writer,
95 config: self.config,
96 bufs: self.bufs,
97 }
98 }
99
100 pub fn with_indent_amount(self, indent_amount: usize) -> Self {
101 let config = Config {
102 indent_amount,
103 ..self.config
104 };
105 Self { config, ..self }
106 }
107
108 pub fn with_indent_lines(self, indent_lines: bool) -> Self {
110 Self {
111 config: self.config.with_indent_lines(indent_lines),
112 ..self
113 }
114 }
115
116 pub fn with_targets(self, targets: bool) -> Self {
119 Self {
120 config: self.config.with_targets(targets),
121 ..self
122 }
123 }
124
125 pub fn with_thread_ids(self, thread_ids: bool) -> Self {
128 Self {
129 config: self.config.with_thread_ids(thread_ids),
130 ..self
131 }
132 }
133
134 pub fn with_thread_names(self, thread_names: bool) -> Self {
137 Self {
138 config: self.config.with_thread_names(thread_names),
139 ..self
140 }
141 }
142
143 pub fn with_wraparound(self, wraparound: usize) -> Self {
147 Self {
148 config: self.config.with_wraparound(wraparound),
149 ..self
150 }
151 }
152
153 pub fn with_verbose_entry(self, verbose_entry: bool) -> Self {
157 Self {
158 config: self.config.with_verbose_entry(verbose_entry),
159 ..self
160 }
161 }
162
163 pub fn with_verbose_exit(self, verbose_exit: bool) -> Self {
167 Self {
168 config: self.config.with_verbose_exit(verbose_exit),
169 ..self
170 }
171 }
172
173 pub fn with_bracketed_fields(self, bracketed_fields: bool) -> Self {
176 Self {
177 config: self.config.with_bracketed_fields(bracketed_fields),
178 ..self
179 }
180 }
181
182 pub fn with_level(self, level: bool) -> Self {
184 Self {
185 config: self.config.with_level(level),
186 ..self
187 }
188 }
189
190 fn styled(&self, style: Style, text: impl AsRef<str>) -> String {
191 if self.config.ansi {
192 style.paint(text.as_ref()).to_string()
193 } else {
194 text.as_ref().to_string()
195 }
196 }
197
198 fn print_kvs<'a, I, V>(&self, buf: &mut impl fmt::Write, kvs: I) -> fmt::Result
199 where
200 I: IntoIterator<Item = (&'a str, V)>,
201 V: fmt::Display + 'a,
202 {
203 let mut kvs = kvs.into_iter();
204 if let Some((k, v)) = kvs.next() {
205 if k == "message" {
206 write!(buf, "{v}")?;
207 } else {
208 write!(buf, "{k}={v}")?;
209 }
210 }
211 for (k, v) in kvs {
212 write!(buf, ", {k}={v}")?;
213 }
214 Ok(())
215 }
216
217 fn write_span_info<S>(&self, id: &Id, ctx: &Context<S>, style: SpanMode)
218 where
219 S: Subscriber + for<'span> LookupSpan<'span>,
220 {
221 let span = ctx
222 .span(id)
223 .expect("in on_enter/on_exit but span does not exist");
224 let ext = span.extensions();
225 let data = ext.get::<Data>().expect("span does not have data");
226
227 let mut guard = self.bufs.lock().unwrap();
228 let bufs = &mut *guard;
229 let mut current_buf = &mut bufs.current_buf;
230
231 let indent = ctx
232 .lookup_current()
233 .as_ref()
234 .map(registry::SpanRef::scope)
235 .map(registry::Scope::from_root)
236 .into_iter()
237 .flatten()
238 .count();
239
240 if self.config.verbose_entry || matches!(style, SpanMode::Open { .. } | SpanMode::Event) {
241 if self.config.targets {
242 let target = span.metadata().target();
243 write!(
244 &mut current_buf,
245 "{}::",
246 self.styled(Style::new().dimmed(), target,),
247 )
248 .expect("Unable to write to buffer");
249 }
250
251 write!(
252 current_buf,
253 "{name}",
254 name = self.styled(Style::new().fg(Color::Green).bold(), span.metadata().name())
255 )
256 .unwrap();
257 if self.config.bracketed_fields {
258 write!(
259 current_buf,
260 "{}",
261 self.styled(Style::new().fg(Color::Green).bold(), "{") )
263 .unwrap();
264 } else {
265 write!(current_buf, " ").unwrap();
266 }
267 self.print_kvs(&mut current_buf, data.kvs.iter().map(|(k, v)| (*k, v)))
268 .unwrap();
269 if self.config.bracketed_fields {
270 write!(
271 current_buf,
272 "{}",
273 self.styled(Style::new().fg(Color::Green).bold(), "}") )
275 .unwrap();
276 }
277 }
278
279 bufs.indent_current(indent, &self.config, style);
280 let writer = self.make_writer.make_writer();
281 bufs.flush_current_buf(writer)
282 }
283}
284
285impl<S, W> Layer<S> for HierarchicalLayer<W>
286where
287 S: Subscriber + for<'span> LookupSpan<'span>,
288 W: for<'writer> MakeWriter<'writer> + 'static,
289{
290 fn on_new_span(&self, attrs: &Attributes, id: &Id, ctx: Context<S>) {
291 let span = ctx.span(id).expect("in new_span but span does not exist");
292 if span.extensions().get::<Data>().is_none() {
293 let data = Data::new(attrs);
294 span.extensions_mut().insert(data);
295 }
296
297 if self.config.verbose_exit {
298 if let Some(span) = span.parent() {
299 self.write_span_info(&span.id(), &ctx, SpanMode::PreOpen);
300 }
301 }
302
303 self.write_span_info(
304 id,
305 &ctx,
306 SpanMode::Open {
307 verbose: self.config.verbose_entry,
308 },
309 );
310 }
311
312 fn on_event(&self, event: &Event<'_>, ctx: Context<S>) {
313 let mut guard = self.bufs.lock().unwrap();
314 let bufs = &mut *guard;
315 let mut event_buf = &mut bufs.current_buf;
316
317 let indent = ctx
319 .event_scope(event)
320 .map(|scope| scope.count())
321 .unwrap_or(0);
322
323 let start = match ctx.current_span().id() {
326 Some(id) => match ctx.span(id) {
327 Some(ctx) => {
329 let ext = ctx.extensions();
330 let data = ext
331 .get::<Data>()
332 .expect("Data cannot be found in extensions");
333 Some(data.start)
334 }
335 None => None,
336 },
337 None => None,
338 };
339 if let Some(start) = start {
340 let elapsed = start.elapsed();
341 write!(
342 &mut event_buf,
343 "{timestamp}{unit} ",
344 timestamp = self.styled(Style::new().dimmed(), elapsed.as_millis().to_string()),
345 unit = self.styled(Style::new().dimmed(), "ms"),
346 )
347 .expect("Unable to write to buffer");
348 }
349
350 #[cfg(feature = "tracing-log")]
351 let normalized_meta = event.normalized_metadata();
352 #[cfg(feature = "tracing-log")]
353 let metadata = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
354 #[cfg(not(feature = "tracing-log"))]
355 let metadata = event.metadata();
356
357 if self.config.level {
358 let level = metadata.level();
359 let level = if self.config.ansi {
360 ColorLevel(level).to_string()
361 } else {
362 level.to_string()
363 };
364 write!(&mut event_buf, "{level}").expect("Unable to write to buffer");
365 }
366
367 if self.config.targets {
368 let target = metadata.target();
369 write!(
370 &mut event_buf,
371 " {}",
372 self.styled(Style::new().dimmed(), target,),
373 )
374 .expect("Unable to write to buffer");
375 }
376
377 let mut visitor = FmtEvent { comma: false, bufs };
378 event.record(&mut visitor);
379 visitor
380 .bufs
381 .indent_current(indent, &self.config, SpanMode::Event);
382 let writer = self.make_writer.make_writer();
383 bufs.flush_current_buf(writer)
384 }
385
386 fn on_close(&self, id: Id, ctx: Context<S>) {
387 self.write_span_info(
388 &id,
389 &ctx,
390 SpanMode::Close {
391 verbose: self.config.verbose_exit,
392 },
393 );
394
395 if self.config.verbose_exit {
396 if let Some(span) = ctx.span(&id).and_then(|span| span.parent()) {
397 self.write_span_info(&span.id(), &ctx, SpanMode::PostClose);
398 }
399 }
400 }
401}