tracing_helpers/
formatter.rs1use std::fmt;
7use std::io;
8use std::io::Write;
9use tracing::field::Visit;
10use tracing_subscriber::field::RecordFields;
11use tracing_subscriber::fmt::FormatFields;
12use tracing_subscriber::fmt::format::Writer;
13
14struct FieldFormatterVisitor<'a> {
15 writer: Writer<'a>,
16 is_empty: bool,
17 result: fmt::Result,
18}
19
20impl FieldFormatterVisitor<'_> {
21 fn maybe_pad(&mut self) {
22 if self.is_empty {
23 self.is_empty = false;
24 } else {
25 self.result = write!(self.writer, " ");
26 }
27 }
28
29 fn record_display(&mut self, field: &tracing::field::Field, value: &dyn fmt::Display) {
30 if self.result.is_err() {
31 return;
32 }
33
34 self.maybe_pad();
35 self.result = match field.name() {
36 "message" => write!(self.writer, "{}", value),
37 name if name.starts_with("log.") => Ok(()),
39 name if name.starts_with("r#") => write!(self.writer, "{}={}", &name[2..], value),
40 name => write!(self.writer, "{}={}", name, value),
41 };
42 }
43}
44
45impl Visit for FieldFormatterVisitor<'_> {
46 fn record_f64(&mut self, field: &tracing::field::Field, value: f64) {
47 self.record_display(field, &value)
48 }
49
50 fn record_i64(&mut self, field: &tracing::field::Field, value: i64) {
51 self.record_display(field, &value)
52 }
53
54 fn record_u64(&mut self, field: &tracing::field::Field, value: u64) {
55 self.record_display(field, &format_args!("{:#x}", value))
57 }
58
59 fn record_bool(&mut self, field: &tracing::field::Field, value: bool) {
60 self.record_display(field, &value)
61 }
62
63 fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
64 self.record_display(field, &format_args!("{:?}", value))
65 }
66
67 fn record_error(
68 &mut self,
69 field: &tracing::field::Field,
70 mut value: &(dyn std::error::Error + 'static),
71 ) {
72 self.record_debug(field, &format_args!("{}", value));
73 while let Some(s) = value.source() {
74 value = s;
75 if self.result.is_err() {
76 return;
77 }
78 self.result = write!(self.writer, ": {}", value);
79 }
80 }
81
82 fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn fmt::Debug) {
83 self.record_display(field, &format_args!("{:x?}", value))
85 }
86}
87
88pub struct FieldFormatter;
94
95impl FormatFields<'_> for FieldFormatter {
96 fn format_fields<R: RecordFields>(&self, writer: Writer<'_>, fields: R) -> fmt::Result {
97 let mut visitor = FieldFormatterVisitor {
98 writer,
99 is_empty: false,
100 result: Ok(()),
101 };
102 fields.record(&mut visitor);
103 visitor.result
104 }
105}
106
107pub struct CrlfWriter<T> {
109 inner: T,
110 write_lf: bool,
111}
112
113impl<T: Write> CrlfWriter<T> {
114 pub fn new(t: T) -> Self {
116 CrlfWriter {
117 inner: t,
118 write_lf: false,
119 }
120 }
121
122 fn flush_lf(&mut self) -> io::Result<()> {
123 if self.write_lf {
124 if self.inner.write(b"\n")? == 0 {
125 return Err(io::ErrorKind::WriteZero.into());
126 }
127 self.write_lf = false;
128 }
129 Ok(())
130 }
131}
132
133impl<T: Write> Write for CrlfWriter<T> {
134 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
135 self.flush_lf()?;
136 if buf.first() == Some(&b'\n') {
137 return Ok(match self.inner.write(b"\r\n")? {
138 0 => 0,
139 1 => {
140 self.write_lf = true;
141 1
142 }
143 _ => 1,
144 });
145 }
146
147 let len = buf.iter().position(|x| *x == b'\n').unwrap_or(buf.len());
148 self.inner.write(&buf[..len])
149 }
150
151 fn flush(&mut self) -> io::Result<()> {
152 self.flush_lf()?;
153 self.inner.flush()
154 }
155}