1 | //! `MakeVisitor` wrappers for working with `fmt::Display` fields. |
2 | use super::{MakeVisitor, VisitFmt, VisitOutput}; |
3 | use tracing_core::field::{Field, Visit}; |
4 | |
5 | use core::fmt; |
6 | |
7 | /// A visitor wrapper that ensures any strings named "message" are formatted |
8 | /// using `fmt::Display` |
9 | #[derive(Debug, Clone)] |
10 | pub struct Messages<V>(V); |
11 | |
12 | // TODO(eliza): When `error` as a primitive type is stable, add a |
13 | // `DisplayErrors` wrapper... |
14 | |
15 | // === impl Messages === |
16 | // |
17 | impl<V> Messages<V> { |
18 | /// Returns a new [`MakeVisitor`] implementation that will wrap `inner` so |
19 | /// that any strings named `message` are formatted using `fmt::Display`. |
20 | /// |
21 | /// [`MakeVisitor`]: super::MakeVisitor |
22 | pub fn new(inner: V) -> Self { |
23 | Messages(inner) |
24 | } |
25 | } |
26 | |
27 | impl<T, V> MakeVisitor<T> for Messages<V> |
28 | where |
29 | V: MakeVisitor<T>, |
30 | { |
31 | type Visitor = Messages<V::Visitor>; |
32 | |
33 | #[inline ] |
34 | fn make_visitor(&self, target: T) -> Self::Visitor { |
35 | Messages(self.0.make_visitor(target)) |
36 | } |
37 | } |
38 | |
39 | impl<V> Visit for Messages<V> |
40 | where |
41 | V: Visit, |
42 | { |
43 | #[inline ] |
44 | fn record_f64(&mut self, field: &Field, value: f64) { |
45 | self.0.record_f64(field, value) |
46 | } |
47 | |
48 | #[inline ] |
49 | fn record_i64(&mut self, field: &Field, value: i64) { |
50 | self.0.record_i64(field, value) |
51 | } |
52 | |
53 | #[inline ] |
54 | fn record_u64(&mut self, field: &Field, value: u64) { |
55 | self.0.record_u64(field, value) |
56 | } |
57 | |
58 | #[inline ] |
59 | fn record_bool(&mut self, field: &Field, value: bool) { |
60 | self.0.record_bool(field, value) |
61 | } |
62 | |
63 | /// Visit a string value. |
64 | fn record_str(&mut self, field: &Field, value: &str) { |
65 | if field.name() == "message" { |
66 | self.0.record_debug(field, &format_args!("{}" , value)) |
67 | } else { |
68 | self.0.record_str(field, value) |
69 | } |
70 | } |
71 | |
72 | // TODO(eliza): add RecordError when stable |
73 | // fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) { |
74 | // self.record_debug(field, &format_args!("{}", value)) |
75 | // } |
76 | |
77 | #[inline ] |
78 | fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { |
79 | self.0.record_debug(field, value) |
80 | } |
81 | } |
82 | |
83 | impl<V, O> VisitOutput<O> for Messages<V> |
84 | where |
85 | V: VisitOutput<O>, |
86 | { |
87 | #[inline ] |
88 | fn finish(self) -> O { |
89 | self.0.finish() |
90 | } |
91 | } |
92 | |
93 | feature! { |
94 | #![feature = "std" ] |
95 | use super::VisitWrite; |
96 | use std::io; |
97 | |
98 | impl<V> VisitWrite for Messages<V> |
99 | where |
100 | V: VisitWrite, |
101 | { |
102 | #[inline ] |
103 | fn writer(&mut self) -> &mut dyn io::Write { |
104 | self.0.writer() |
105 | } |
106 | } |
107 | } |
108 | |
109 | impl<V> VisitFmt for Messages<V> |
110 | where |
111 | V: VisitFmt, |
112 | { |
113 | #[inline ] |
114 | fn writer(&mut self) -> &mut dyn fmt::Write { |
115 | self.0.writer() |
116 | } |
117 | } |
118 | |