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 new(inner: V) -> Self22 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] make_visitor(&self, target: T) -> Self::Visitor34 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] record_f64(&mut self, field: &Field, value: f64)44 fn record_f64(&mut self, field: &Field, value: f64) { 45 self.0.record_f64(field, value) 46 } 47 48 #[inline] record_i64(&mut self, field: &Field, value: i64)49 fn record_i64(&mut self, field: &Field, value: i64) { 50 self.0.record_i64(field, value) 51 } 52 53 #[inline] record_u64(&mut self, field: &Field, value: u64)54 fn record_u64(&mut self, field: &Field, value: u64) { 55 self.0.record_u64(field, value) 56 } 57 58 #[inline] record_bool(&mut self, field: &Field, value: bool)59 fn record_bool(&mut self, field: &Field, value: bool) { 60 self.0.record_bool(field, value) 61 } 62 63 /// Visit a string value. record_str(&mut self, field: &Field, value: &str)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] record_debug(&mut self, field: &Field, value: &dyn fmt::Debug)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] finish(self) -> O88 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] writer(&mut self) -> &mut dyn fmt::Write114 fn writer(&mut self) -> &mut dyn fmt::Write { 115 self.0.writer() 116 } 117 } 118