tracing_indicatif/
util.rs

1//! Provides some general tracing utilities that are useful for this crate, for example a utility
2//! to filter "indicatif.pb_show" and "indicatif.pb_hide" from printing spans.
3use std::fmt;
4
5use tracing::field::Visit;
6use tracing_core::Field;
7use tracing_subscriber::field::RecordFields;
8use tracing_subscriber::{
9    field::{MakeVisitor, VisitFmt, VisitOutput},
10    fmt::{format::Writer, FormatFields},
11};
12
13/// Wraps around an existing struct that impls [`FormatFields`], but allows for filtering specific
14/// fields from spans or events.
15pub struct FilteredFormatFields<Format, Filter> {
16    format: Format,
17    filter: Filter,
18}
19
20impl<'writer, Format, Filter> FilteredFormatFields<Format, Filter>
21where
22    Format: MakeVisitor<Writer<'writer>>,
23    Format::Visitor: VisitFmt + VisitOutput<fmt::Result>,
24    Filter: Clone + Fn(&Field) -> bool,
25{
26    /// Wraps around an existing struct that impls [`FormatFields`], but filters out any fields which
27    /// returns _false_ when passed into `filter`.
28    pub fn new(format: Format, filter: Filter) -> Self {
29        Self { format, filter }
30    }
31}
32
33impl<'writer, Format, Filter> FormatFields<'writer> for FilteredFormatFields<Format, Filter>
34where
35    Format: MakeVisitor<Writer<'writer>>,
36    Format::Visitor: VisitFmt + VisitOutput<fmt::Result>,
37    Filter: Clone + Fn(&Field) -> bool,
38{
39    fn format_fields<R: RecordFields>(
40        &self,
41        writer: Writer<'writer>,
42        fields: R,
43    ) -> std::fmt::Result {
44        let mut v =
45            FilteredFormatFieldsVisitor::new(self.format.make_visitor(writer), self.filter.clone());
46        fields.record(&mut v);
47        v.finish()?;
48
49        Ok(())
50    }
51}
52
53struct FilteredFormatFieldsVisitor<Visitor, Filter> {
54    visitor: Visitor,
55    filter: Filter,
56}
57
58impl<Visitor, Filter> FilteredFormatFieldsVisitor<Visitor, Filter> {
59    fn new(visitor: Visitor, filter: Filter) -> Self {
60        Self { visitor, filter }
61    }
62}
63
64impl<Visitor, Filter> Visit for FilteredFormatFieldsVisitor<Visitor, Filter>
65where
66    Visitor: Visit,
67    Filter: Fn(&Field) -> bool,
68{
69    fn record_debug(&mut self, field: &tracing_core::Field, value: &dyn std::fmt::Debug) {
70        if (self.filter)(field) {
71            self.visitor.record_debug(field, value);
72        }
73    }
74
75    fn record_f64(&mut self, field: &tracing_core::Field, value: f64) {
76        if (self.filter)(field) {
77            self.visitor.record_f64(field, value);
78        }
79    }
80
81    fn record_i64(&mut self, field: &tracing_core::Field, value: i64) {
82        if (self.filter)(field) {
83            self.visitor.record_i64(field, value);
84        }
85    }
86
87    fn record_u64(&mut self, field: &tracing_core::Field, value: u64) {
88        if (self.filter)(field) {
89            self.visitor.record_u64(field, value);
90        }
91    }
92
93    fn record_str(&mut self, field: &tracing_core::Field, value: &str) {
94        if (self.filter)(field) {
95            self.visitor.record_str(field, value);
96        }
97    }
98
99    fn record_i128(&mut self, field: &tracing_core::Field, value: i128) {
100        if (self.filter)(field) {
101            self.visitor.record_i128(field, value);
102        }
103    }
104
105    fn record_u128(&mut self, field: &tracing_core::Field, value: u128) {
106        if (self.filter)(field) {
107            self.visitor.record_u128(field, value);
108        }
109    }
110
111    fn record_bool(&mut self, field: &tracing_core::Field, value: bool) {
112        if (self.filter)(field) {
113            self.visitor.record_bool(field, value);
114        }
115    }
116
117    fn record_error(
118        &mut self,
119        field: &tracing_core::Field,
120        value: &(dyn std::error::Error + 'static),
121    ) {
122        if (self.filter)(field) {
123            self.visitor.record_error(field, value);
124        }
125    }
126}
127
128impl<Visitor, Filter> VisitOutput<fmt::Result> for FilteredFormatFieldsVisitor<Visitor, Filter>
129where
130    Visitor: VisitOutput<fmt::Result>,
131    Filter: Fn(&Field) -> bool,
132{
133    fn finish(self) -> fmt::Result {
134        self.visitor.finish()
135    }
136}
137
138impl<Visitor, Filter> VisitFmt for FilteredFormatFieldsVisitor<Visitor, Filter>
139where
140    Visitor: VisitFmt,
141    Filter: Fn(&Field) -> bool,
142{
143    fn writer(&mut self) -> &mut dyn fmt::Write {
144        self.visitor.writer()
145    }
146}