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
use std::{fmt, io, time::Instant};
use tracing::{
field::{Field, Visit},
Event, Level, Subscriber,
};
use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer};
#[derive(Debug, Default)]
struct FmtEventVisitor {
message: String,
}
impl Visit for FmtEventVisitor {
fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
match field.name() {
"message" => self.message = format!("{:?}", value),
_ => {}
}
}
}
enum StandardOutput {
Out(io::Stdout),
Err(io::Stderr),
}
impl StandardOutput {
fn new(level: &Level) -> Self {
match *level {
Level::ERROR | Level::WARN => Self::Err(io::stderr()),
_ => Self::Out(io::stdout()),
}
}
fn get_dyn_ref(&mut self) -> &mut dyn io::Write {
match self {
Self::Out(out) => out,
Self::Err(err) => err,
}
}
}
pub struct FmtLayer {
start: Instant,
}
impl FmtLayer {
pub fn new() -> Self {
FmtLayer {
start: Instant::now(),
}
}
}
impl<S> Layer<S> for FmtLayer
where
S: Subscriber + for<'span> LookupSpan<'span>,
{
fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
let now = Instant::now();
let time = now - self.start;
let mut visitor = FmtEventVisitor::default();
event.record(&mut visitor);
let mut span_string = String::new();
for span in ctx.scope() {
if !span_string.is_empty() {
span_string.push_str(" | ");
}
span_string.push_str(span.name());
}
let metadata = event.metadata();
let level = match *metadata.level() {
Level::ERROR => "ERROR",
Level::WARN => "WARN",
Level::INFO => "INFO",
Level::DEBUG => "DEBUG",
Level::TRACE => "TRACE",
};
let module = metadata.module_path().unwrap_or("no module");
let mut output = StandardOutput::new(metadata.level());
let output_ref = output.get_dyn_ref();
writeln!(
output_ref,
"[{:.6} {}]({})({}): {}",
time.as_secs_f64(),
level,
span_string,
module,
visitor.message,
)
.unwrap();
}
}