wgpu_subscriber/
fmt_layer.rs1use std::{fmt, io, time::Instant};
2use tracing::{
3 field::{Field, Visit},
4 Event, Level, Subscriber,
5};
6use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer};
7
8#[derive(Debug, Default)]
9struct FmtEventVisitor {
10 message: String,
11}
12
13impl Visit for FmtEventVisitor {
14 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
15 match field.name() {
16 "message" => self.message = format!("{:?}", value),
17 _ => {}
18 }
19 }
20}
21
22enum StandardOutput {
23 Out(io::Stdout),
24 Err(io::Stderr),
25}
26
27impl StandardOutput {
28 fn new(level: &Level) -> Self {
29 match *level {
30 Level::ERROR | Level::WARN => Self::Err(io::stderr()),
31 _ => Self::Out(io::stdout()),
32 }
33 }
34
35 fn get_dyn_ref(&mut self) -> &mut dyn io::Write {
36 match self {
37 Self::Out(out) => out,
38 Self::Err(err) => err,
39 }
40 }
41}
42
43pub struct FmtLayer {
48 start: Instant,
49}
50
51impl FmtLayer {
52 pub fn new() -> Self {
53 FmtLayer {
54 start: Instant::now(),
55 }
56 }
57}
58
59impl<S> Layer<S> for FmtLayer
60where
61 S: Subscriber + for<'span> LookupSpan<'span>,
62{
63 fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
64 let now = Instant::now();
65 let time = now - self.start;
66
67 let mut visitor = FmtEventVisitor::default();
68 event.record(&mut visitor);
69
70 let mut span_string = String::new();
71 for span in ctx.scope() {
72 if !span_string.is_empty() {
73 span_string.push_str(" | ");
74 }
75 span_string.push_str(span.name());
76 }
77
78 let metadata = event.metadata();
79 let level = match *metadata.level() {
80 Level::ERROR => "ERROR",
81 Level::WARN => "WARN",
82 Level::INFO => "INFO",
83 Level::DEBUG => "DEBUG",
84 Level::TRACE => "TRACE",
85 };
86
87 let module = metadata.module_path().unwrap_or("no module");
88
89 let mut output = StandardOutput::new(metadata.level());
90 let output_ref = output.get_dyn_ref();
91
92 writeln!(
93 output_ref,
94 "[{:.6} {}]({})({}): {}",
95 time.as_secs_f64(),
96 level,
97 span_string,
98 module,
99 visitor.message,
100 )
101 .unwrap();
102 }
103}