1use std::{
22 fmt,
23 ops::Deref,
24 str,
25 sync::{
26 atomic::{AtomicU8, Ordering},
27 Arc,
28 },
29};
30
31use log::{
32 kv::{Error, Key, ToKey, Value, VisitSource},
33 *,
34};
35
36pub trait Filter: log::kv::Source {
37 fn is_enabled(&self, _level: Level) -> bool;
39
40 #[doc(hidden)]
42 #[inline(always)]
43 fn _private_api_log(
44 &self, args: fmt::Arguments, level: Level,
45 &(target, module_path, file, line): &(&str, &str, &str, u32),
46 ) {
47 let record = RecordBuilder::new()
48 .level(level)
49 .target(target)
50 .module_path(Some(module_path))
51 .file(Some(file))
52 .line(Some(line))
53 .args(args)
54 .build();
55 logger().log(&record);
56 }
57}
58
59impl<T: Filter> Filter for Arc<T> {
60 #[inline(always)]
61 fn is_enabled(&self, _level: Level) -> bool {
62 Filter::is_enabled(self.as_ref(), _level)
63 }
64}
65
66impl<T: Filter> Filter for &T {
67 #[inline(always)]
68 fn is_enabled(&self, _level: Level) -> bool {
69 Filter::is_enabled(*self, _level)
70 }
71}
72
73pub struct LogFilter {
92 max_level: AtomicU8,
93}
94
95impl LogFilter {
96 pub fn new() -> Self {
97 Self { max_level: AtomicU8::new(Level::Trace as u8) }
98 }
99
100 #[inline]
102 pub fn set_level(&self, level: Level) {
103 self.max_level.store(level as u8, Ordering::Relaxed);
104 }
105
106 #[inline]
107 pub fn get_level(&self) -> u8 {
108 self.max_level.load(Ordering::Relaxed)
109 }
110}
111
112impl Filter for LogFilter {
113 #[inline(always)]
114 fn is_enabled(&self, level: Level) -> bool {
115 level as u8 <= self.max_level.load(Ordering::Relaxed)
116 }
117}
118
119impl log::kv::Source for LogFilter {
120 #[inline(always)]
121 fn visit<'kvs>(&'kvs self, _visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
122 Ok(())
123 }
124
125 #[inline(always)]
126 fn get<'a>(&'a self, _key: Key) -> Option<Value<'a>> {
127 return None;
128 }
129
130 #[inline(always)]
131 fn count(&self) -> usize {
132 0
133 }
134}
135
136#[derive(Clone)]
138pub struct GlobalFilter {
139 max_level: &'static AtomicU8,
140}
141
142impl GlobalFilter {
143 pub fn new(max_level: &'static AtomicU8) -> Self {
144 Self { max_level }
145 }
146
147 #[inline]
149 pub fn set_level(&self, level: Level) {
150 self.max_level.store(level as u8, Ordering::Relaxed);
151 }
152
153 #[inline]
154 pub fn get_level(&self) -> u8 {
155 self.max_level.load(Ordering::Relaxed)
156 }
157}
158
159impl Filter for GlobalFilter {
160 #[inline(always)]
161 fn is_enabled(&self, level: Level) -> bool {
162 level as u8 <= self.max_level.load(Ordering::Relaxed)
163 }
164}
165
166impl log::kv::Source for GlobalFilter {
167 #[inline(always)]
168 fn visit<'kvs>(&'kvs self, _visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
169 Ok(())
170 }
171
172 #[inline(always)]
173 fn get<'a>(&'a self, _key: Key) -> Option<Value<'a>> {
174 return None;
175 }
176
177 #[inline(always)]
178 fn count(&self) -> usize {
179 0
180 }
181}
182
183#[derive(Default)]
185pub struct DummyFilter();
186
187impl DummyFilter {
188 #[inline(always)]
189 pub fn new() -> Self {
190 DummyFilter()
191 }
192}
193
194impl Filter for DummyFilter {
195 #[inline(always)]
196 fn is_enabled(&self, _level: Level) -> bool {
197 true
198 }
199}
200
201impl log::kv::Source for DummyFilter {
202 #[inline(always)]
203 fn visit<'kvs>(&'kvs self, _visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
204 Ok(())
205 }
206
207 #[inline(always)]
208 fn get<'a>(&'a self, _key: Key) -> Option<Value<'a>> {
209 return None;
210 }
211
212 #[inline(always)]
213 fn count(&self) -> usize {
214 0
215 }
216}
217
218pub struct KeyFilter<T, V>
271where
272 T: Filter,
273 V: log::kv::ToValue,
274{
275 inner: T,
276 key: &'static str,
277 value: V,
278}
279
280impl<T, V> Clone for KeyFilter<T, V>
281where
282 T: Filter + Clone,
283 V: log::kv::ToValue + Clone,
284{
285 #[inline]
286 fn clone(&self) -> Self {
287 Self { inner: self.inner.clone(), key: self.key, value: self.value.clone() }
288 }
289}
290
291impl<T, V> Deref for KeyFilter<T, V>
292where
293 T: Filter,
294 V: log::kv::ToValue,
295{
296 type Target = T;
297 #[inline]
298 fn deref(&self) -> &T {
299 &self.inner
300 }
301}
302
303impl<T, V> KeyFilter<T, V>
304where
305 T: Filter,
306 V: log::kv::ToValue,
307{
308 #[inline]
309 pub fn with(inner: T, key: &'static str, value: V) -> Self {
310 Self { inner, key, value }
311 }
312}
313
314impl<T, V> log::kv::Source for KeyFilter<T, V>
315where
316 T: Filter,
317 V: log::kv::ToValue,
318{
319 #[inline(always)]
320 fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
321 visitor.visit_pair(self.key.to_key(), self.value.to_value())
322 }
323
324 #[inline(always)]
325 fn get<'a>(&'a self, key: Key) -> Option<Value<'a>> {
326 if key.as_ref() == self.key {
327 return Some(self.value.to_value());
328 }
329 return None;
330 }
331
332 #[inline(always)]
333 fn count(&self) -> usize {
334 1
335 }
336}
337
338impl<T, V> Filter for KeyFilter<T, V>
339where
340 T: Filter,
341 V: log::kv::ToValue,
342{
343 #[inline(always)]
344 fn is_enabled(&self, level: Level) -> bool {
345 self.inner.is_enabled(level)
346 }
347
348 #[doc(hidden)]
350 #[inline(always)]
351 fn _private_api_log(
352 &self, args: fmt::Arguments, level: Level,
353 &(target, module_path, file, line): &(&str, &str, &str, u32),
354 ) {
355 let record = RecordBuilder::new()
357 .level(level)
358 .target(target)
359 .module_path(Some(module_path))
360 .file(Some(file))
361 .line(Some(line))
362 .key_values(&self)
363 .args(args)
364 .build();
365 logger().log(&record);
366 }
367}
368
369impl<V> KeyFilter<DummyFilter, V>
370where
371 V: log::kv::ToValue,
372{
373 #[inline]
374 pub fn new(key: &'static str, value: V) -> Self {
375 Self { inner: DummyFilter(), key, value }
376 }
377}