1use crate::{
2 filter::LevelFilter,
3 layer::{Context, Layer},
4};
5use core::{any::type_name, fmt, marker::PhantomData};
6use tracing_core::{Interest, Metadata, Subscriber};
7
8/// A filter implemented by a closure or function pointer that
9/// determines whether a given span or event is enabled, based on its
10/// [`Metadata`].
11///
12/// This type can be used for both [per-layer filtering][plf] (using its
13/// [`Filter`] implementation) and [global filtering][global] (using its
14/// [`Layer`] implementation).
15///
16/// See the [documentation on filtering with layers][filtering] for details.
17///
18/// [`Metadata`]: tracing_core::Metadata
19/// [`Filter`]: crate::layer::Filter
20/// [`Layer`]: crate::layer::Layer
21/// [plf]: crate::layer#per-layer-filtering
22/// [global]: crate::layer#global-filtering
23/// [filtering]: crate::layer#filtering-with-layers
24#[derive(Clone)]
25pub struct FilterFn<F = fn(&Metadata<'_>) -> bool> {
26 enabled: F,
27 max_level_hint: Option<LevelFilter>,
28}
29
30/// A filter implemented by a closure or function pointer that
31/// determines whether a given span or event is enabled _dynamically_,
32/// potentially based on the current [span context].
33///
34/// This type can be used for both [per-layer filtering][plf] (using its
35/// [`Filter`] implementation) and [global filtering][global] (using its
36/// [`Layer`] implementation).
37///
38/// See the [documentation on filtering with layers][filtering] for details.
39///
40/// [span context]: crate::layer::Context
41/// [`Filter`]: crate::layer::Filter
42/// [`Layer`]: crate::layer::Layer
43/// [plf]: crate::layer#per-layer-filtering
44/// [global]: crate::layer#global-filtering
45/// [filtering]: crate::layer#filtering-with-layers
46pub struct DynFilterFn<
47 S,
48 // TODO(eliza): should these just be boxed functions?
49 F = fn(&Metadata<'_>, &Context<'_, S>) -> bool,
50 R = fn(&'static Metadata<'static>) -> Interest,
51> {
52 enabled: F,
53 register_callsite: Option<R>,
54 max_level_hint: Option<LevelFilter>,
55 _s: PhantomData<fn(S)>,
56}
57
58// === impl FilterFn ===
59
60/// Constructs a [`FilterFn`], from a function or closure that returns `true` if
61/// a span or event should be enabled, based on its [`Metadata`].
62///
63/// The returned [`FilterFn`] can be used for both [per-layer filtering][plf]
64/// (using its [`Filter`] implementation) and [global filtering][global] (using
65/// its [`Layer`] implementation).
66///
67/// See the [documentation on filtering with layers][filtering] for details.
68///
69/// This is equivalent to calling [`FilterFn::new`].
70///
71/// [`Metadata`]: tracing_core::Metadata
72/// [`Filter`]: crate::layer::Filter
73/// [`Layer`]: crate::layer::Layer
74/// [plf]: crate::layer#per-layer-filtering
75/// [global]: crate::layer#global-filtering
76/// [filtering]: crate::layer#filtering-with-layers
77///
78/// # Examples
79///
80/// ```
81/// use tracing_subscriber::{
82/// layer::{Layer, SubscriberExt},
83/// filter,
84/// util::SubscriberInitExt,
85/// };
86///
87/// let my_filter = filter::filter_fn(|metadata| {
88/// // Only enable spans or events with the target "interesting_things"
89/// metadata.target() == "interesting_things"
90/// });
91///
92/// let my_layer = tracing_subscriber::fmt::layer();
93///
94/// tracing_subscriber::registry()
95/// .with(my_layer.with_filter(my_filter))
96/// .init();
97///
98/// // This event will not be enabled.
99/// tracing::warn!("something important but uninteresting happened!");
100///
101/// // This event will be enabled.
102/// tracing::debug!(target: "interesting_things", "an interesting minor detail...");
103/// ```
104pub fn filter_fn<F>(f: F) -> FilterFn<F>
105where
106 F: Fn(&Metadata<'_>) -> bool,
107{
108 FilterFn::new(enabled:f)
109}
110
111/// Constructs a [`DynFilterFn`] from a function or closure that returns `true`
112/// if a span or event should be enabled within a particular [span context][`Context`].
113///
114/// This is equivalent to calling [`DynFilterFn::new`].
115///
116/// Unlike [`filter_fn`], this function takes a closure or function pointer
117/// taking the [`Metadata`] for a span or event *and* the current [`Context`].
118/// This means that a [`DynFilterFn`] can choose whether to enable spans or
119/// events based on information about the _current_ span (or its parents).
120///
121/// If this is *not* necessary, use [`filter_fn`] instead.
122///
123/// The returned [`DynFilterFn`] can be used for both [per-layer filtering][plf]
124/// (using its [`Filter`] implementation) and [global filtering][global] (using
125/// its [`Layer`] implementation).
126///
127/// See the [documentation on filtering with layers][filtering] for details.
128///
129/// # Examples
130///
131/// ```
132/// use tracing_subscriber::{
133/// layer::{Layer, SubscriberExt},
134/// filter,
135/// util::SubscriberInitExt,
136/// };
137///
138/// // Only enable spans or events within a span named "interesting_span".
139/// let my_filter = filter::dynamic_filter_fn(|metadata, cx| {
140/// // If this *is* "interesting_span", make sure to enable it.
141/// if metadata.is_span() && metadata.name() == "interesting_span" {
142/// return true;
143/// }
144///
145/// // Otherwise, are we in an interesting span?
146/// if let Some(current_span) = cx.lookup_current() {
147/// return current_span.name() == "interesting_span";
148/// }
149///
150/// false
151/// });
152///
153/// let my_layer = tracing_subscriber::fmt::layer();
154///
155/// tracing_subscriber::registry()
156/// .with(my_layer.with_filter(my_filter))
157/// .init();
158///
159/// // This event will not be enabled.
160/// tracing::info!("something happened");
161///
162/// tracing::info_span!("interesting_span").in_scope(|| {
163/// // This event will be enabled.
164/// tracing::debug!("something else happened");
165/// });
166/// ```
167///
168/// [`Filter`]: crate::layer::Filter
169/// [`Layer`]: crate::layer::Layer
170/// [plf]: crate::layer#per-layer-filtering
171/// [global]: crate::layer#global-filtering
172/// [filtering]: crate::layer#filtering-with-layers
173/// [`Context`]: crate::layer::Context
174/// [`Metadata`]: tracing_core::Metadata
175pub fn dynamic_filter_fn<S, F>(f: F) -> DynFilterFn<S, F>
176where
177 F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool,
178{
179 DynFilterFn::new(enabled:f)
180}
181
182impl<F> FilterFn<F>
183where
184 F: Fn(&Metadata<'_>) -> bool,
185{
186 /// Constructs a [`FilterFn`] from a function or closure that returns `true`
187 /// if a span or event should be enabled, based on its [`Metadata`].
188 ///
189 /// If determining whether a span or event should be enabled also requires
190 /// information about the current span context, use [`DynFilterFn`] instead.
191 ///
192 /// See the [documentation on per-layer filtering][plf] for details on using
193 /// [`Filter`]s.
194 ///
195 /// [`Filter`]: crate::layer::Filter
196 /// [plf]: crate::layer#per-layer-filtering
197 /// [`Metadata`]: tracing_core::Metadata
198 ///
199 /// # Examples
200 ///
201 /// ```
202 /// use tracing_subscriber::{
203 /// layer::{Layer, SubscriberExt},
204 /// filter::FilterFn,
205 /// util::SubscriberInitExt,
206 /// };
207 ///
208 /// let my_filter = FilterFn::new(|metadata| {
209 /// // Only enable spans or events with the target "interesting_things"
210 /// metadata.target() == "interesting_things"
211 /// });
212 ///
213 /// let my_layer = tracing_subscriber::fmt::layer();
214 ///
215 /// tracing_subscriber::registry()
216 /// .with(my_layer.with_filter(my_filter))
217 /// .init();
218 ///
219 /// // This event will not be enabled.
220 /// tracing::warn!("something important but uninteresting happened!");
221 ///
222 /// // This event will be enabled.
223 /// tracing::debug!(target: "interesting_things", "an interesting minor detail...");
224 /// ```
225 pub fn new(enabled: F) -> Self {
226 Self {
227 enabled,
228 max_level_hint: None,
229 }
230 }
231
232 /// Sets the highest verbosity [`Level`] the filter function will enable.
233 ///
234 /// The value passed to this method will be returned by this `FilterFn`'s
235 /// [`Filter::max_level_hint`] method.
236 ///
237 /// If the provided function will not enable all levels, it is recommended
238 /// to call this method to configure it with the most verbose level it will
239 /// enable.
240 ///
241 /// # Examples
242 ///
243 /// ```
244 /// use tracing_subscriber::{
245 /// layer::{Layer, SubscriberExt},
246 /// filter::{filter_fn, LevelFilter},
247 /// util::SubscriberInitExt,
248 /// };
249 /// use tracing_core::Level;
250 ///
251 /// let my_filter = filter_fn(|metadata| {
252 /// // Only enable spans or events with targets starting with `my_crate`
253 /// // and levels at or below `INFO`.
254 /// metadata.level() <= &Level::INFO && metadata.target().starts_with("my_crate")
255 /// })
256 /// // Since the filter closure will only enable the `INFO` level and
257 /// // below, set the max level hint
258 /// .with_max_level_hint(LevelFilter::INFO);
259 ///
260 /// let my_layer = tracing_subscriber::fmt::layer();
261 ///
262 /// tracing_subscriber::registry()
263 /// .with(my_layer.with_filter(my_filter))
264 /// .init();
265 /// ```
266 ///
267 /// [`Level`]: tracing_core::Level
268 /// [`Filter::max_level_hint`]: crate::layer::Filter::max_level_hint
269 pub fn with_max_level_hint(self, max_level_hint: impl Into<LevelFilter>) -> Self {
270 Self {
271 max_level_hint: Some(max_level_hint.into()),
272 ..self
273 }
274 }
275
276 #[inline]
277 pub(in crate::filter) fn is_enabled(&self, metadata: &Metadata<'_>) -> bool {
278 let enabled = (self.enabled)(metadata);
279 debug_assert!(
280 !enabled || self.is_below_max_level(metadata),
281 "FilterFn<{}> claimed it would only enable {:?} and below, \
282 but it enabled metadata with the {:?} level\nmetadata={:#?}",
283 type_name::<F>(),
284 self.max_level_hint.unwrap(),
285 metadata.level(),
286 metadata,
287 );
288
289 enabled
290 }
291
292 #[inline]
293 pub(in crate::filter) fn is_callsite_enabled(
294 &self,
295 metadata: &'static Metadata<'static>,
296 ) -> Interest {
297 // Because `self.enabled` takes a `Metadata` only (and no `Context`
298 // parameter), we can reasonably assume its results are cachable, and
299 // just return `Interest::always`/`Interest::never`.
300 if (self.enabled)(metadata) {
301 debug_assert!(
302 self.is_below_max_level(metadata),
303 "FilterFn<{}> claimed it was only interested in {:?} and below, \
304 but it enabled metadata with the {:?} level\nmetadata={:#?}",
305 type_name::<F>(),
306 self.max_level_hint.unwrap(),
307 metadata.level(),
308 metadata,
309 );
310 return Interest::always();
311 }
312
313 Interest::never()
314 }
315
316 fn is_below_max_level(&self, metadata: &Metadata<'_>) -> bool {
317 self.max_level_hint
318 .as_ref()
319 .map(|hint| metadata.level() <= hint)
320 .unwrap_or(true)
321 }
322}
323
324impl<S, F> Layer<S> for FilterFn<F>
325where
326 F: Fn(&Metadata<'_>) -> bool + 'static,
327 S: Subscriber,
328{
329 fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool {
330 self.is_enabled(metadata)
331 }
332
333 fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
334 self.is_callsite_enabled(metadata)
335 }
336
337 fn max_level_hint(&self) -> Option<LevelFilter> {
338 self.max_level_hint
339 }
340}
341
342impl<F> From<F> for FilterFn<F>
343where
344 F: Fn(&Metadata<'_>) -> bool,
345{
346 fn from(enabled: F) -> Self {
347 Self::new(enabled)
348 }
349}
350
351impl<F> fmt::Debug for FilterFn<F> {
352 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353 f&mut DebugStruct<'_, '_>.debug_struct("FilterFn")
354 .field("enabled", &format_args!("{}", type_name::<F>()))
355 .field(name:"max_level_hint", &self.max_level_hint)
356 .finish()
357 }
358}
359
360// === impl DynFilterFn ==
361
362impl<S, F> DynFilterFn<S, F>
363where
364 F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool,
365{
366 /// Constructs a [`Filter`] from a function or closure that returns `true`
367 /// if a span or event should be enabled in the current [span
368 /// context][`Context`].
369 ///
370 /// Unlike [`FilterFn`], a `DynFilterFn` is constructed from a closure or
371 /// function pointer that takes both the [`Metadata`] for a span or event
372 /// *and* the current [`Context`]. This means that a [`DynFilterFn`] can
373 /// choose whether to enable spans or events based on information about the
374 /// _current_ span (or its parents).
375 ///
376 /// If this is *not* necessary, use [`FilterFn`] instead.
377 ///
378 /// See the [documentation on per-layer filtering][plf] for details on using
379 /// [`Filter`]s.
380 ///
381 /// [`Filter`]: crate::layer::Filter
382 /// [plf]: crate::layer#per-layer-filtering
383 /// [`Context`]: crate::layer::Context
384 /// [`Metadata`]: tracing_core::Metadata
385 ///
386 /// # Examples
387 ///
388 /// ```
389 /// use tracing_subscriber::{
390 /// layer::{Layer, SubscriberExt},
391 /// filter::DynFilterFn,
392 /// util::SubscriberInitExt,
393 /// };
394 ///
395 /// // Only enable spans or events within a span named "interesting_span".
396 /// let my_filter = DynFilterFn::new(|metadata, cx| {
397 /// // If this *is* "interesting_span", make sure to enable it.
398 /// if metadata.is_span() && metadata.name() == "interesting_span" {
399 /// return true;
400 /// }
401 ///
402 /// // Otherwise, are we in an interesting span?
403 /// if let Some(current_span) = cx.lookup_current() {
404 /// return current_span.name() == "interesting_span";
405 /// }
406 ///
407 /// false
408 /// });
409 ///
410 /// let my_layer = tracing_subscriber::fmt::layer();
411 ///
412 /// tracing_subscriber::registry()
413 /// .with(my_layer.with_filter(my_filter))
414 /// .init();
415 ///
416 /// // This event will not be enabled.
417 /// tracing::info!("something happened");
418 ///
419 /// tracing::info_span!("interesting_span").in_scope(|| {
420 /// // This event will be enabled.
421 /// tracing::debug!("something else happened");
422 /// });
423 /// ```
424 pub fn new(enabled: F) -> Self {
425 Self {
426 enabled,
427 register_callsite: None,
428 max_level_hint: None,
429 _s: PhantomData,
430 }
431 }
432}
433
434impl<S, F, R> DynFilterFn<S, F, R>
435where
436 F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool,
437{
438 /// Sets the highest verbosity [`Level`] the filter function will enable.
439 ///
440 /// The value passed to this method will be returned by this `DynFilterFn`'s
441 /// [`Filter::max_level_hint`] method.
442 ///
443 /// If the provided function will not enable all levels, it is recommended
444 /// to call this method to configure it with the most verbose level it will
445 /// enable.
446 ///
447 /// # Examples
448 ///
449 /// ```
450 /// use tracing_subscriber::{
451 /// layer::{Layer, SubscriberExt},
452 /// filter::{DynFilterFn, LevelFilter},
453 /// util::SubscriberInitExt,
454 /// };
455 /// use tracing_core::Level;
456 ///
457 /// // Only enable spans or events with levels at or below `INFO`, if
458 /// // we are inside a span called "interesting_span".
459 /// let my_filter = DynFilterFn::new(|metadata, cx| {
460 /// // If the level is greater than INFO, disable it.
461 /// if metadata.level() > &Level::INFO {
462 /// return false;
463 /// }
464 ///
465 /// // If any span in the current scope is named "interesting_span",
466 /// // enable this span or event.
467 /// for span in cx.lookup_current().iter().flat_map(|span| span.scope()) {
468 /// if span.name() == "interesting_span" {
469 /// return true;
470 /// }
471 /// }
472 ///
473 /// // Otherwise, disable it.
474 /// false
475 /// })
476 /// // Since the filter closure will only enable the `INFO` level and
477 /// // below, set the max level hint
478 /// .with_max_level_hint(LevelFilter::INFO);
479 ///
480 /// let my_layer = tracing_subscriber::fmt::layer();
481 ///
482 /// tracing_subscriber::registry()
483 /// .with(my_layer.with_filter(my_filter))
484 /// .init();
485 /// ```
486 ///
487 /// [`Level`]: tracing_core::Level
488 /// [`Filter::max_level_hint`]: crate::layer::Filter::max_level_hint
489 pub fn with_max_level_hint(self, max_level_hint: impl Into<LevelFilter>) -> Self {
490 Self {
491 max_level_hint: Some(max_level_hint.into()),
492 ..self
493 }
494 }
495
496 /// Adds a function for filtering callsites to this filter.
497 ///
498 /// When this filter's [`Filter::callsite_enabled`][cse] method is called,
499 /// the provided function will be used rather than the default.
500 ///
501 /// By default, `DynFilterFn` assumes that, because the filter _may_ depend
502 /// dynamically on the current [span context], its result should never be
503 /// cached. However, some filtering strategies may require dynamic information
504 /// from the current span context in *some* cases, but are able to make
505 /// static filtering decisions from [`Metadata`] alone in others.
506 ///
507 /// For example, consider the filter given in the example for
508 /// [`DynFilterFn::new`]. That filter enables all spans named
509 /// "interesting_span", and any events and spans that occur inside of an
510 /// interesting span. Since the span's name is part of its static
511 /// [`Metadata`], the "interesting_span" can be enabled in
512 /// [`callsite_enabled`][cse]:
513 ///
514 /// ```
515 /// use tracing_subscriber::{
516 /// layer::{Layer, SubscriberExt},
517 /// filter::DynFilterFn,
518 /// util::SubscriberInitExt,
519 /// };
520 /// use tracing_core::subscriber::Interest;
521 ///
522 /// // Only enable spans or events within a span named "interesting_span".
523 /// let my_filter = DynFilterFn::new(|metadata, cx| {
524 /// // If this *is* "interesting_span", make sure to enable it.
525 /// if metadata.is_span() && metadata.name() == "interesting_span" {
526 /// return true;
527 /// }
528 ///
529 /// // Otherwise, are we in an interesting span?
530 /// if let Some(current_span) = cx.lookup_current() {
531 /// return current_span.name() == "interesting_span";
532 /// }
533 ///
534 /// false
535 /// }).with_callsite_filter(|metadata| {
536 /// // If this is an "interesting_span", we know we will always
537 /// // enable it.
538 /// if metadata.is_span() && metadata.name() == "interesting_span" {
539 /// return Interest::always();
540 /// }
541 ///
542 /// // Otherwise, it depends on whether or not we're in an interesting
543 /// // span. You'll have to ask us again for each span/event!
544 /// Interest::sometimes()
545 /// });
546 ///
547 /// let my_layer = tracing_subscriber::fmt::layer();
548 ///
549 /// tracing_subscriber::registry()
550 /// .with(my_layer.with_filter(my_filter))
551 /// .init();
552 /// ```
553 ///
554 /// [cse]: crate::layer::Filter::callsite_enabled
555 /// [`enabled`]: crate::layer::Filter::enabled
556 /// [`Metadata`]: tracing_core::Metadata
557 /// [span context]: crate::layer::Context
558 pub fn with_callsite_filter<R2>(self, callsite_enabled: R2) -> DynFilterFn<S, F, R2>
559 where
560 R2: Fn(&'static Metadata<'static>) -> Interest,
561 {
562 let register_callsite = Some(callsite_enabled);
563 let DynFilterFn {
564 enabled,
565 max_level_hint,
566 _s,
567 ..
568 } = self;
569 DynFilterFn {
570 enabled,
571 register_callsite,
572 max_level_hint,
573 _s,
574 }
575 }
576
577 fn default_callsite_enabled(&self, metadata: &Metadata<'_>) -> Interest {
578 // If it's below the configured max level, assume that `enabled` will
579 // never enable it...
580 if !is_below_max_level(&self.max_level_hint, metadata) {
581 debug_assert!(
582 !(self.enabled)(metadata, &Context::none()),
583 "DynFilterFn<{}> claimed it would only enable {:?} and below, \
584 but it enabled metadata with the {:?} level\nmetadata={:#?}",
585 type_name::<F>(),
586 self.max_level_hint.unwrap(),
587 metadata.level(),
588 metadata,
589 );
590 return Interest::never();
591 }
592
593 // Otherwise, since this `enabled` function is dynamic and depends on
594 // the current context, we don't know whether this span or event will be
595 // enabled or not. Ask again every time it's recorded!
596 Interest::sometimes()
597 }
598}
599
600impl<S, F, R> DynFilterFn<S, F, R>
601where
602 F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool,
603 R: Fn(&'static Metadata<'static>) -> Interest,
604{
605 #[inline]
606 fn is_enabled(&self, metadata: &Metadata<'_>, cx: &Context<'_, S>) -> bool {
607 let enabled = (self.enabled)(metadata, cx);
608 debug_assert!(
609 !enabled || is_below_max_level(&self.max_level_hint, metadata),
610 "DynFilterFn<{}> claimed it would only enable {:?} and below, \
611 but it enabled metadata with the {:?} level\nmetadata={:#?}",
612 type_name::<F>(),
613 self.max_level_hint.unwrap(),
614 metadata.level(),
615 metadata,
616 );
617
618 enabled
619 }
620
621 #[inline]
622 fn is_callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest {
623 let interest = self
624 .register_callsite
625 .as_ref()
626 .map(|callsite_enabled| callsite_enabled(metadata))
627 .unwrap_or_else(|| self.default_callsite_enabled(metadata));
628 debug_assert!(
629 interest.is_never() || is_below_max_level(&self.max_level_hint, metadata),
630 "DynFilterFn<{}, {}> claimed it was only interested in {:?} and below, \
631 but it enabled metadata with the {:?} level\nmetadata={:#?}",
632 type_name::<F>(),
633 type_name::<R>(),
634 self.max_level_hint.unwrap(),
635 metadata.level(),
636 metadata,
637 );
638
639 interest
640 }
641}
642
643impl<S, F, R> Layer<S> for DynFilterFn<S, F, R>
644where
645 F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool + 'static,
646 R: Fn(&'static Metadata<'static>) -> Interest + 'static,
647 S: Subscriber,
648{
649 fn enabled(&self, metadata: &Metadata<'_>, cx: Context<'_, S>) -> bool {
650 self.is_enabled(metadata, &cx)
651 }
652
653 fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
654 self.is_callsite_enabled(metadata)
655 }
656
657 fn max_level_hint(&self) -> Option<LevelFilter> {
658 self.max_level_hint
659 }
660}
661
662impl<S, F, R> fmt::Debug for DynFilterFn<S, F, R> {
663 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
664 let mut s: DebugStruct<'_, '_> = f.debug_struct(name:"DynFilterFn");
665 s.field(name:"enabled", &format_args!("{}", type_name::<F>()));
666 if self.register_callsite.is_some() {
667 s.field(
668 name:"register_callsite",
669 &format_args!("Some({})", type_name::<R>()),
670 );
671 } else {
672 s.field(name:"register_callsite", &format_args!("None"));
673 }
674
675 s.field(name:"max_level_hint", &self.max_level_hint).finish()
676 }
677}
678
679impl<S, F, R> Clone for DynFilterFn<S, F, R>
680where
681 F: Clone,
682 R: Clone,
683{
684 fn clone(&self) -> Self {
685 Self {
686 enabled: self.enabled.clone(),
687 register_callsite: self.register_callsite.clone(),
688 max_level_hint: self.max_level_hint,
689 _s: PhantomData,
690 }
691 }
692}
693
694impl<F, S> From<F> for DynFilterFn<S, F>
695where
696 F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool,
697{
698 fn from(f: F) -> Self {
699 Self::new(enabled:f)
700 }
701}
702
703// === PLF impls ===
704
705feature! {
706 #![all(feature = "registry", feature = "std")]
707 use crate::layer::Filter;
708
709 impl<S, F> Filter<S> for FilterFn<F>
710 where
711 F: Fn(&Metadata<'_>) -> bool,
712 {
713 fn enabled(&self, metadata: &Metadata<'_>, _: &Context<'_, S>) -> bool {
714 self.is_enabled(metadata)
715 }
716
717 fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest {
718 self.is_callsite_enabled(metadata)
719 }
720
721 fn max_level_hint(&self) -> Option<LevelFilter> {
722 self.max_level_hint
723 }
724 }
725
726 impl<S, F, R> Filter<S> for DynFilterFn<S, F, R>
727 where
728 F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool,
729 R: Fn(&'static Metadata<'static>) -> Interest,
730 {
731 fn enabled(&self, metadata: &Metadata<'_>, cx: &Context<'_, S>) -> bool {
732 self.is_enabled(metadata, cx)
733 }
734
735 fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest {
736 self.is_callsite_enabled(metadata)
737 }
738
739 fn max_level_hint(&self) -> Option<LevelFilter> {
740 self.max_level_hint
741 }
742 }
743}
744
745fn is_below_max_level(hint: &Option<LevelFilter>, metadata: &Metadata<'_>) -> bool {
746 hint.as_ref()
747 .map(|hint| metadata.level() <= hint)
748 .unwrap_or(default:true)
749}
750