foundations/telemetry/log/
field_filtering.rs1use 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 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}