1pub(crate) mod format;
2pub mod time;
3
4use crate::time::FormatTime;
5use format::{write_span_mode, Buffers, ColorLevel, Config, FmtEvent, SpanMode};
6
7use nu_ansi_term::{Color, Style};
8use std::{
9 fmt::{self, Write},
10 io::{self, IsTerminal},
11 iter::Fuse,
12 mem,
13 sync::{
14 atomic::{AtomicBool, Ordering},
15 Mutex,
16 },
17 thread::LocalKey,
18 time::Instant,
19};
20use tracing_core::{
21 field::{Field, Visit},
22 span::{Attributes, Id},
23 Event, Subscriber,
24};
25#[cfg(feature = "tracing-log")]
26use tracing_log::NormalizeEvent;
27use tracing_subscriber::{
28 fmt::MakeWriter,
29 layer::{Context, Layer},
30 registry::{LookupSpan, ScopeFromRoot, SpanRef},
31};
32
33pub(crate) struct Data {
35 start: Instant,
36 kvs: Vec<(&'static str, String)>,
37 written: bool,
38}
39
40impl Data {
41 pub fn new(attrs: &Attributes<'_>, written: bool) -> Self {
42 let mut span = Self {
43 start: Instant::now(),
44 kvs: Vec::new(),
45 written,
46 };
47 attrs.record(&mut span);
48 span
49 }
50}
51
52impl Visit for Data {
53 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
54 self.kvs.push((field.name(), format!("{:?}", value)))
55 }
56}
57
58#[derive(Debug)]
59pub struct HierarchicalLayer<W = fn() -> io::Stderr, FT = ()>
60where
61 W: for<'writer> MakeWriter<'writer> + 'static,
62 FT: FormatTime,
63{
64 make_writer: W,
65 bufs: Mutex<Buffers>,
66 config: Config,
67 timer: FT,
68}
69
70impl Default for HierarchicalLayer {
71 fn default() -> Self {
72 Self::new(2)
73 }
74}
75
76impl HierarchicalLayer<fn() -> io::Stderr> {
77 pub fn new(indent_amount: usize) -> Self {
78 let ansi = io::stderr().is_terminal();
79 let config = Config {
80 ansi,
81 indent_amount,
82 ..Default::default()
83 };
84 Self {
85 make_writer: io::stderr,
86 bufs: Mutex::new(Buffers::new()),
87 config,
88 timer: (),
89 }
90 }
91}
92
93impl<W, FT> HierarchicalLayer<W, FT>
94where
95 W: for<'writer> MakeWriter<'writer> + 'static,
96 FT: FormatTime,
97{
98 pub fn with_ansi(self, ansi: bool) -> Self {
100 Self {
101 config: self.config.with_ansi(ansi),
102 ..self
103 }
104 }
105
106 pub fn with_writer<W2>(self, make_writer: W2) -> HierarchicalLayer<W2, FT>
107 where
108 W2: for<'writer> MakeWriter<'writer>,
109 {
110 HierarchicalLayer {
111 make_writer,
112 config: self.config,
113 bufs: self.bufs,
114 timer: self.timer,
115 }
116 }
117
118 pub fn with_indent_amount(self, indent_amount: usize) -> Self {
119 let config = Config {
120 indent_amount,
121 ..self.config
122 };
123 Self { config, ..self }
124 }
125
126 pub fn with_indent_lines(self, indent_lines: bool) -> Self {
128 Self {
129 config: self.config.with_indent_lines(indent_lines),
130 ..self
131 }
132 }
133
134 pub fn with_timer<FT2: FormatTime>(self, timer: FT2) -> HierarchicalLayer<W, FT2> {
136 HierarchicalLayer {
137 make_writer: self.make_writer,
138 config: self.config,
139 bufs: self.bufs,
140 timer,
141 }
142 }
143
144 pub fn with_targets(self, targets: bool) -> Self {
147 Self {
148 config: self.config.with_targets(targets),
149 ..self
150 }
151 }
152
153 pub fn with_thread_ids(self, thread_ids: bool) -> Self {
156 Self {
157 config: self.config.with_thread_ids(thread_ids),
158 ..self
159 }
160 }
161
162 pub fn with_thread_names(self, thread_names: bool) -> Self {
165 Self {
166 config: self.config.with_thread_names(thread_names),
167 ..self
168 }
169 }
170
171 pub fn with_wraparound(self, wraparound: usize) -> Self {
175 Self {
176 config: self.config.with_wraparound(wraparound),
177 ..self
178 }
179 }
180
181 pub fn with_verbose_entry(self, verbose_entry: bool) -> Self {
185 Self {
186 config: self.config.with_verbose_entry(verbose_entry),
187 ..self
188 }
189 }
190
191 pub fn with_verbose_exit(self, verbose_exit: bool) -> Self {
195 Self {
196 config: self.config.with_verbose_exit(verbose_exit),
197 ..self
198 }
199 }
200
201 pub fn with_span_retrace(self, enabled: bool) -> Self {
206 Self {
207 config: self.config.with_span_retrace(enabled),
208 ..self
209 }
210 }
211
212 pub fn with_deferred_spans(self, enabled: bool) -> Self {
216 Self {
217 config: self.config.with_deferred_spans(enabled),
218 ..self
219 }
220 }
221
222 pub fn with_span_modes(self, enabled: bool) -> Self {
224 Self {
225 config: self.config.with_span_modes(enabled),
226 ..self
227 }
228 }
229
230 pub fn with_bracketed_fields(self, bracketed_fields: bool) -> Self {
233 Self {
234 config: self.config.with_bracketed_fields(bracketed_fields),
235 ..self
236 }
237 }
238
239 fn styled(&self, style: Style, text: impl AsRef<str>) -> String {
240 styled(self.config.ansi, style, text)
241 }
242
243 fn print_kvs<'a, I, V>(&self, buf: &mut impl fmt::Write, kvs: I) -> fmt::Result
244 where
245 I: IntoIterator<Item = (&'a str, V)>,
246 V: fmt::Display + 'a,
247 {
248 let mut kvs = kvs.into_iter();
249 if let Some((k, v)) = kvs.next() {
250 if k == "message" {
251 write!(buf, "{}", v)?;
252 } else {
253 write!(buf, "{}={}", k, v)?;
254 }
255 }
256 for (k, v) in kvs {
257 write!(buf, ", {}={}", k, v)?;
258 }
259 Ok(())
260 }
261
262 fn write_retrace_span<'a, S>(
264 &self,
265 new_span: &SpanRef<'a, S>,
266 bufs: &mut Buffers,
267 ctx: &'a Context<S>,
268 pre_open: bool,
269 ) where
270 S: Subscriber + for<'new_span> LookupSpan<'new_span>,
271 {
272 let old_span_id = bufs.current_span.replace((new_span.id()).clone());
279 let old_span_id = old_span_id.as_ref();
280 let new_span_id = new_span.id();
281
282 if Some(&new_span_id) != old_span_id {
283 let old_span = old_span_id.as_ref().and_then(|v| ctx.span(v));
284 let old_path = old_span.as_ref().map(scope_path).into_iter().flatten();
285
286 let new_path = scope_path(new_span);
287
288 let new_path = DifferenceIter::new(old_path, new_path, |v| v.id());
290
291 for (i, span) in new_path.enumerate() {
292 let was_written = if let Some(data) = span.extensions_mut().get_mut::<Data>() {
294 mem::replace(&mut data.written, true)
295 } else {
296 false
300 };
301
302 let mut verbose = false;
304 if i == 0 && pre_open {
305 if let Some(span) = span.parent() {
306 verbose = true;
307 self.write_span_info(&span, bufs, SpanMode::PreOpen);
308 }
309 }
310
311 self.write_span_info(
312 &span,
313 bufs,
314 if was_written {
315 SpanMode::Retrace { verbose }
316 } else {
317 SpanMode::Open { verbose }
318 },
319 )
320 }
321 }
322 }
323
324 fn write_span_info<S>(&self, span: &SpanRef<S>, bufs: &mut Buffers, style: SpanMode)
325 where
326 S: Subscriber + for<'span> LookupSpan<'span>,
327 {
328 let ext = span.extensions();
329 let data = ext.get::<Data>().expect("span does not have data");
330
331 let mut current_buf = &mut bufs.current_buf;
332
333 if self.config.span_modes {
334 write_span_mode(current_buf, style)
335 }
336
337 let indent = scope_path(span).skip(1).count();
338
339 let should_write = match style {
340 SpanMode::Open { .. } | SpanMode::Event => true,
341 SpanMode::PreOpen { .. } if self.config.verbose_entry => true,
343 SpanMode::Close { verbose } => verbose,
344 SpanMode::Retrace { .. } => true,
346 SpanMode::PostClose => true,
348 _ => false,
349 };
350
351 if should_write {
352 if self.config.targets {
353 let target = span.metadata().target();
354 write!(
355 &mut current_buf,
356 "{}::",
357 self.styled(Style::new().dimmed(), target,),
358 )
359 .expect("Unable to write to buffer");
360 }
361
362 write!(
363 current_buf,
364 "{name}",
365 name = self.styled(Style::new().fg(Color::Green).bold(), span.metadata().name())
366 )
367 .unwrap();
368 if self.config.bracketed_fields {
369 write!(
370 current_buf,
371 "{}",
372 self.styled(Style::new().fg(Color::Green).bold(), "{") )
374 .unwrap();
375 } else {
376 write!(current_buf, " ").unwrap();
377 }
378 self.print_kvs(&mut current_buf, data.kvs.iter().map(|(k, v)| (*k, v)))
379 .unwrap();
380 if self.config.bracketed_fields {
381 write!(
382 current_buf,
383 "{}",
384 self.styled(Style::new().fg(Color::Green).bold(), "}") )
386 .unwrap();
387 }
388 }
389
390 bufs.indent_current(indent, &self.config, style);
391 let writer = self.make_writer.make_writer();
392 bufs.flush_current_buf(writer)
393 }
394
395 fn write_timestamp<S>(&self, span: SpanRef<S>, buf: &mut String)
396 where
397 S: Subscriber + for<'span> LookupSpan<'span>,
398 {
399 let ext = span.extensions();
400 let data = ext
401 .get::<Data>()
402 .expect("Data cannot be found in extensions");
403
404 self.timer
405 .style_timestamp(self.config.ansi, data.start.elapsed(), buf)
406 .unwrap()
407 }
408
409 fn is_recursive() -> Option<RecursiveGuard> {
410 thread_local! {
411 pub static IS_EMPTY: AtomicBool = const { AtomicBool::new(true) };
412 }
413
414 IS_EMPTY.with(|is_empty| {
415 is_empty
416 .compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed)
417 .ok()
418 .map(|_| RecursiveGuard(&IS_EMPTY))
419 })
420 }
421}
422
423fn styled(ansi: bool, style: Style, text: impl AsRef<str>) -> String {
424 if ansi {
425 style.paint(text.as_ref()).to_string()
426 } else {
427 text.as_ref().to_string()
428 }
429}
430
431struct RecursiveGuard(&'static LocalKey<AtomicBool>);
432
433impl Drop for RecursiveGuard {
434 fn drop(&mut self) {
435 self.0
436 .with(|is_empty| is_empty.store(true, Ordering::Relaxed));
437 }
438}
439
440impl<S, W, FT> Layer<S> for HierarchicalLayer<W, FT>
441where
442 S: Subscriber + for<'span> LookupSpan<'span>,
443 W: for<'writer> MakeWriter<'writer> + 'static,
444 FT: FormatTime + 'static,
445{
446 fn on_new_span(&self, attrs: &Attributes, id: &Id, ctx: Context<S>) {
447 let Some(_guard) = Self::is_recursive() else {
448 return;
449 };
450
451 let span = ctx.span(id).expect("in new_span but span does not exist");
452
453 if span.extensions().get::<Data>().is_none() {
454 let data = Data::new(attrs, !self.config.deferred_spans);
455 span.extensions_mut().insert(data);
456 }
457
458 if self.config.deferred_spans {
460 return;
461 }
462
463 let bufs = &mut *self.bufs.lock().unwrap();
464
465 if self.config.span_retrace {
466 self.write_retrace_span(&span, bufs, &ctx, self.config.verbose_entry);
467 } else {
468 if self.config.verbose_entry {
469 if let Some(span) = span.parent() {
470 self.write_span_info(&span, bufs, SpanMode::PreOpen);
471 }
472 }
473 bufs.current_span = Some(span.id());
475 self.write_span_info(
476 &span,
477 bufs,
478 SpanMode::Open {
479 verbose: self.config.verbose_entry,
480 },
481 );
482 }
483 }
484
485 fn on_event(&self, event: &Event<'_>, ctx: Context<S>) {
486 let Some(_guard) = Self::is_recursive() else {
487 return;
488 };
489
490 let span = ctx.current_span();
491 let span_id = span.id();
492 let span = span_id.and_then(|id| ctx.span(id));
493
494 let mut guard = self.bufs.lock().unwrap();
495 let bufs = &mut *guard;
496
497 if let Some(new_span) = &span {
498 if self.config.span_retrace || self.config.deferred_spans {
499 self.write_retrace_span(new_span, bufs, &ctx, self.config.verbose_entry);
500 }
501 }
502
503 let mut event_buf = &mut bufs.current_buf;
504
505 {
508 let prev_buffer_len = event_buf.len();
509
510 self.timer
511 .format_time(&mut event_buf)
512 .expect("Unable to write time to buffer");
513
514 if prev_buffer_len < event_buf.len() {
516 write!(event_buf, " ").expect("Unable to write to buffer");
517 }
518 }
519
520 let deindent = if self.config.indent_lines { 0 } else { 1 };
521 let indent = ctx
523 .event_scope(event)
524 .map(|scope| scope.count() - deindent)
525 .unwrap_or(0);
526
527 if let Some(span) = span {
530 self.write_timestamp(span, event_buf);
531 event_buf.push(' ');
532 }
533
534 #[cfg(feature = "tracing-log")]
535 let normalized_meta = event.normalized_metadata();
536 #[cfg(feature = "tracing-log")]
537 let metadata = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
538 #[cfg(not(feature = "tracing-log"))]
539 let metadata = event.metadata();
540
541 let level = metadata.level();
542 let level = if self.config.ansi {
543 ColorLevel(level).to_string()
544 } else {
545 level.to_string()
546 };
547
548 write!(&mut event_buf, "{level}", level = level).expect("Unable to write to buffer");
549
550 if self.config.targets {
551 let target = metadata.target();
552 write!(
553 &mut event_buf,
554 " {}",
555 self.styled(Style::new().dimmed(), target,),
556 )
557 .expect("Unable to write to buffer");
558 }
559
560 let mut visitor = FmtEvent { comma: false, bufs };
561 event.record(&mut visitor);
562 visitor
563 .bufs
564 .indent_current(indent, &self.config, SpanMode::Event);
565 let writer = self.make_writer.make_writer();
566 bufs.flush_current_buf(writer)
567 }
568
569 fn on_close(&self, id: Id, ctx: Context<S>) {
570 let Some(_guard) = Self::is_recursive() else {
571 return;
572 };
573
574 let bufs = &mut *self.bufs.lock().unwrap();
575
576 let span = ctx.span(&id).expect("invalid span in on_close");
577
578 if self.config.deferred_spans
580 && span.extensions().get::<Data>().map(|v| v.written) != Some(true)
581 {
582 return;
583 }
584
585 self.write_span_info(
588 &span,
589 bufs,
590 SpanMode::Close {
591 verbose: self.config.verbose_exit,
592 },
593 );
594
595 if let Some(parent_span) = span.parent() {
596 bufs.current_span = Some(parent_span.id());
597 if self.config.verbose_exit {
598 self.write_span_info(&parent_span, bufs, SpanMode::PostClose);
601 }
602 }
603 }
604}
605
606fn scope_path<'a, R: LookupSpan<'a>>(span: &SpanRef<'a, R>) -> ScopeFromRoot<'a, R> {
607 span.scope().from_root()
608}
609
610struct DifferenceIter<L, R, F> {
612 left: Fuse<L>,
613 right: R,
614 compare: F,
615}
616
617impl<L: Iterator<Item = T>, R: Iterator<Item = T>, T, U: PartialEq, F: Fn(&T) -> U>
618 DifferenceIter<L, R, F>
619{
620 fn new(left: L, right: R, compare: F) -> Self {
621 Self {
622 left: left.fuse(),
623 right,
624 compare,
625 }
626 }
627}
628
629impl<L: Iterator<Item = T>, R: Iterator<Item = T>, T, U: PartialEq, F: Fn(&T) -> U> Iterator
630 for DifferenceIter<L, R, F>
631{
632 type Item = T;
633
634 fn next(&mut self) -> Option<Self::Item> {
635 loop {
636 let left = self.left.next();
637 let right = self.right.next()?;
638
639 if left.as_ref().map(&self.compare) != Some((self.compare)(&right)) {
640 return Some(right);
641 }
642 }
643 }
644}