Skip to main content

foundations/telemetry/log/
field_filtering.rs

1use slog::{BorrowedKV, Drain, KV, Key, OwnedKV, OwnedKVList, Record, RecordStatic, Serializer};
2use std::fmt::Arguments;
3use std::panic::RefUnwindSafe;
4
5pub(crate) trait Filter {
6    fn filter(&mut self, key: &Key) -> bool;
7}
8
9pub(crate) trait FilterFactory: Clone {
10    type Filter: Filter;
11
12    fn create_filter(&self) -> Self::Filter;
13
14    /// Fast path to disable a [`Filter`] for a given record.
15    fn filter_active(&self, _record: &Record, _values: &OwnedKVList) -> bool {
16        true
17    }
18}
19
20pub(crate) struct FieldFilteringDrain<F, D> {
21    inner: D,
22    filter_factory: F,
23}
24
25impl<F, D> FieldFilteringDrain<F, D> {
26    pub(crate) fn new(inner: D, filter_factory: F) -> Self {
27        Self {
28            inner,
29            filter_factory,
30        }
31    }
32}
33
34impl<F, D> Drain for FieldFilteringDrain<F, D>
35where
36    F: FilterFactory + Send + Sync + RefUnwindSafe + 'static,
37    D: Drain,
38{
39    type Ok = D::Ok;
40    type Err = D::Err;
41
42    fn log(&self, record: &Record, values: &OwnedKVList) -> Result<Self::Ok, Self::Err> {
43        if !self.filter_factory.filter_active(record, values) {
44            return self.inner.log(record, values);
45        }
46
47        let context_fields_kv = FieldFilteringKV {
48            inner: values.clone(),
49            filter_factory: self.filter_factory.clone(),
50        };
51
52        let record_fields_kv = FieldFilteringKV {
53            inner: record.kv(),
54            filter_factory: self.filter_factory.clone(),
55        };
56
57        let record_static = RecordStatic {
58            location: record.location(),
59            tag: record.tag(),
60            level: record.level(),
61        };
62
63        let filtered_record =
64            Record::new(&record_static, record.msg(), BorrowedKV(&record_fields_kv));
65
66        self.inner
67            .log(&filtered_record, &OwnedKV(context_fields_kv).into())
68    }
69
70    #[inline]
71    fn is_enabled(&self, level: slog::Level) -> bool {
72        Drain::is_enabled(&self.inner, level)
73    }
74
75    #[inline]
76    fn flush(&self) -> Result<(), slog::FlushError> {
77        Drain::flush(&self.inner)
78    }
79}
80
81struct FieldFilteringKV<K, F> {
82    inner: K,
83    filter_factory: F,
84}
85
86impl<K, F> KV for FieldFilteringKV<K, F>
87where
88    K: KV,
89    F: FilterFactory,
90{
91    fn serialize(&self, record: &Record, inner: &mut dyn Serializer) -> slog::Result {
92        let mut serializer = FieldFilteringSerializer {
93            inner,
94            filter: self.filter_factory.create_filter(),
95        };
96
97        self.inner.serialize(record, &mut serializer)
98    }
99}
100
101struct FieldFilteringSerializer<'s, F> {
102    inner: &'s mut dyn Serializer,
103    filter: F,
104}
105
106macro_rules! filter {
107    ( $self:ident.$fn:ident($key:expr, $val:expr) ) => {{
108        if !$self.filter.filter(&$key) {
109            return Ok(());
110        }
111
112        $self.inner.$fn($key, $val)
113    }};
114}
115
116impl<F: Filter> Serializer for FieldFilteringSerializer<'_, F> {
117    fn emit_arguments(&mut self, key: Key, val: &Arguments) -> slog::Result {
118        filter!(self.emit_arguments(key, val))
119    }
120
121    fn emit_usize(&mut self, key: Key, val: usize) -> slog::Result {
122        filter!(self.emit_usize(key, val))
123    }
124
125    fn emit_isize(&mut self, key: Key, val: isize) -> slog::Result {
126        filter!(self.emit_isize(key, val))
127    }
128
129    fn emit_bool(&mut self, key: Key, val: bool) -> slog::Result {
130        filter!(self.emit_bool(key, val))
131    }
132
133    fn emit_char(&mut self, key: Key, val: char) -> slog::Result {
134        filter!(self.emit_char(key, val))
135    }
136
137    fn emit_u8(&mut self, key: Key, val: u8) -> slog::Result {
138        filter!(self.emit_u8(key, val))
139    }
140
141    fn emit_i8(&mut self, key: Key, val: i8) -> slog::Result {
142        filter!(self.emit_i8(key, val))
143    }
144
145    fn emit_u16(&mut self, key: Key, val: u16) -> slog::Result {
146        filter!(self.emit_u16(key, val))
147    }
148
149    fn emit_i16(&mut self, key: Key, val: i16) -> slog::Result {
150        filter!(self.emit_i16(key, val))
151    }
152
153    fn emit_u32(&mut self, key: Key, val: u32) -> slog::Result {
154        filter!(self.emit_u32(key, val))
155    }
156
157    fn emit_i32(&mut self, key: Key, val: i32) -> slog::Result {
158        filter!(self.emit_i32(key, val))
159    }
160
161    fn emit_f32(&mut self, key: Key, val: f32) -> slog::Result {
162        filter!(self.emit_f32(key, val))
163    }
164
165    fn emit_u64(&mut self, key: Key, val: u64) -> slog::Result {
166        filter!(self.emit_u64(key, val))
167    }
168
169    fn emit_i64(&mut self, key: Key, val: i64) -> slog::Result {
170        filter!(self.emit_i64(key, val))
171    }
172
173    fn emit_f64(&mut self, key: Key, val: f64) -> slog::Result {
174        filter!(self.emit_f64(key, val))
175    }
176
177    #[cfg(integer128)]
178    fn emit_u128(&mut self, key: Key, val: u128) -> slog::Result {
179        filter!(self.emit_u128(key, val))
180    }
181
182    #[cfg(integer128)]
183    fn emit_i128(&mut self, key: Key, val: i128) -> slog::Result {
184        filter!(self.emit_i128(key, val))
185    }
186
187    fn emit_str(&mut self, key: Key, val: &str) -> slog::Result {
188        filter!(self.emit_str(key, val))
189    }
190
191    fn emit_unit(&mut self, key: Key) -> slog::Result {
192        if !self.filter.filter(&key) {
193            return Ok(());
194        }
195
196        self.inner.emit_unit(key)
197    }
198
199    fn emit_none(&mut self, key: Key) -> slog::Result {
200        if !self.filter.filter(&key) {
201            return Ok(());
202        }
203
204        self.inner.emit_none(key)
205    }
206}