tracing_subscriber/field/
display.rs

1//! `MakeVisitor` wrappers for working with `fmt::Display` fields.
2use super::{MakeVisitor, VisitFmt, VisitOutput};
3use tracing_core::field::{Field, Visit};
4
5use core::fmt;
6
7/// A visitor wrapper that ensures any strings named "message" are formatted
8/// using `fmt::Display`
9#[derive(Debug, Clone)]
10pub 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//
17impl<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
27impl<T, V> MakeVisitor<T> for Messages<V>
28where
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
39impl<V> Visit for Messages<V>
40where
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
83impl<V, O> VisitOutput<O> for Messages<V>
84where
85    V: VisitOutput<O>,
86{
87    #[inline]
88    fn finish(self) -> O {
89        self.0.finish()
90    }
91}
92
93feature! {
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
109impl<V> VisitFmt for Messages<V>
110where
111    V: VisitFmt,
112{
113    #[inline]
114    fn writer(&mut self) -> &mut dyn fmt::Write {
115        self.0.writer()
116    }
117}