• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::{
2     filter::LevelFilter,
3     layer::{Context, Layer},
4 };
5 use core::{any::type_name, fmt, marker::PhantomData};
6 use 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)]
25 pub 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
46 pub 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 /// ```
filter_fn<F>(f: F) -> FilterFn<F> where F: Fn(&Metadata<'_>) -> bool,104 pub fn filter_fn<F>(f: F) -> FilterFn<F>
105 where
106     F: Fn(&Metadata<'_>) -> bool,
107 {
108     FilterFn::new(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
dynamic_filter_fn<S, F>(f: F) -> DynFilterFn<S, F> where F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool,175 pub fn dynamic_filter_fn<S, F>(f: F) -> DynFilterFn<S, F>
176 where
177     F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool,
178 {
179     DynFilterFn::new(f)
180 }
181 
182 impl<F> FilterFn<F>
183 where
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     /// ```
new(enabled: F) -> Self225     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
with_max_level_hint(self, max_level_hint: impl Into<LevelFilter>) -> Self269     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]
is_enabled(&self, metadata: &Metadata<'_>) -> bool277     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]
is_callsite_enabled( &self, metadata: &'static Metadata<'static>, ) -> Interest293     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 cacheable, 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 
is_below_max_level(&self, metadata: &Metadata<'_>) -> bool316     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 
324 impl<S, F> Layer<S> for FilterFn<F>
325 where
326     F: Fn(&Metadata<'_>) -> bool + 'static,
327     S: Subscriber,
328 {
enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool329     fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool {
330         self.is_enabled(metadata)
331     }
332 
register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest333     fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
334         self.is_callsite_enabled(metadata)
335     }
336 
max_level_hint(&self) -> Option<LevelFilter>337     fn max_level_hint(&self) -> Option<LevelFilter> {
338         self.max_level_hint
339     }
340 }
341 
342 impl<F> From<F> for FilterFn<F>
343 where
344     F: Fn(&Metadata<'_>) -> bool,
345 {
from(enabled: F) -> Self346     fn from(enabled: F) -> Self {
347         Self::new(enabled)
348     }
349 }
350 
351 impl<F> fmt::Debug for FilterFn<F> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result352     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353         f.debug_struct("FilterFn")
354             .field("enabled", &format_args!("{}", type_name::<F>()))
355             .field("max_level_hint", &self.max_level_hint)
356             .finish()
357     }
358 }
359 
360 // === impl DynFilterFn ==
361 
362 impl<S, F> DynFilterFn<S, F>
363 where
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     /// ```
new(enabled: F) -> Self424     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 
434 impl<S, F, R> DynFilterFn<S, F, R>
435 where
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
with_max_level_hint(self, max_level_hint: impl Into<LevelFilter>) -> Self489     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
with_callsite_filter<R2>(self, callsite_enabled: R2) -> DynFilterFn<S, F, R2> where R2: Fn(&'static Metadata<'static>) -> Interest,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 
default_callsite_enabled(&self, metadata: &Metadata<'_>) -> Interest577     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 
600 impl<S, F, R> DynFilterFn<S, F, R>
601 where
602     F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool,
603     R: Fn(&'static Metadata<'static>) -> Interest,
604 {
605     #[inline]
is_enabled(&self, metadata: &Metadata<'_>, cx: &Context<'_, S>) -> bool606     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]
is_callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest622     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 
643 impl<S, F, R> Layer<S> for DynFilterFn<S, F, R>
644 where
645     F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool + 'static,
646     R: Fn(&'static Metadata<'static>) -> Interest + 'static,
647     S: Subscriber,
648 {
enabled(&self, metadata: &Metadata<'_>, cx: Context<'_, S>) -> bool649     fn enabled(&self, metadata: &Metadata<'_>, cx: Context<'_, S>) -> bool {
650         self.is_enabled(metadata, &cx)
651     }
652 
register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest653     fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
654         self.is_callsite_enabled(metadata)
655     }
656 
max_level_hint(&self) -> Option<LevelFilter>657     fn max_level_hint(&self) -> Option<LevelFilter> {
658         self.max_level_hint
659     }
660 }
661 
662 impl<S, F, R> fmt::Debug for DynFilterFn<S, F, R> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result663     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
664         let mut s = f.debug_struct("DynFilterFn");
665         s.field("enabled", &format_args!("{}", type_name::<F>()));
666         if self.register_callsite.is_some() {
667             s.field(
668                 "register_callsite",
669                 &format_args!("Some({})", type_name::<R>()),
670             );
671         } else {
672             s.field("register_callsite", &format_args!("None"));
673         }
674 
675         s.field("max_level_hint", &self.max_level_hint).finish()
676     }
677 }
678 
679 impl<S, F, R> Clone for DynFilterFn<S, F, R>
680 where
681     F: Clone,
682     R: Clone,
683 {
clone(&self) -> Self684     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 
694 impl<F, S> From<F> for DynFilterFn<S, F>
695 where
696     F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool,
697 {
from(f: F) -> Self698     fn from(f: F) -> Self {
699         Self::new(f)
700     }
701 }
702 
703 // === PLF impls ===
704 
705 feature! {
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 
is_below_max_level(hint: &Option<LevelFilter>, metadata: &Metadata<'_>) -> bool745 fn is_below_max_level(hint: &Option<LevelFilter>, metadata: &Metadata<'_>) -> bool {
746     hint.as_ref()
747         .map(|hint| metadata.level() <= hint)
748         .unwrap_or(true)
749 }
750