Skip to content

Commit 1b2a054

Browse files
CAD97davidbarskyhawkw
authored
subscriber: clarify filter.not() docs w.r.t. event_enabled (#2251)
* Explain filter.not() w.r.t. event_enabled Co-authored-by: David Barsky <[email protected]> Co-authored-by: Eliza Weisman <[email protected]>
1 parent bfd0e55 commit 1b2a054

File tree

2 files changed

+98
-6
lines changed

2 files changed

+98
-6
lines changed

tracing-subscriber/src/filter/subscriber_filters/combinator.rs

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -405,9 +405,55 @@ where
405405
///
406406
/// This inverts the values returned by the [`enabled`] and [`callsite_enabled`]
407407
/// methods on the wrapped filter; it does *not* invert [`event_enabled`], as
408-
/// implementing that method is optional, and filters which do not implement
409-
/// filtering on event field values will return `true` even for events that their
410-
/// [`enabled`] method would disable.
408+
/// filters which do not implement filtering on event field values will return
409+
/// the default `true` even for events that their [`enabled`] method disables.
410+
///
411+
/// Consider a normal filter defined as:
412+
///
413+
/// ```ignore (pseudo-code)
414+
/// // for spans
415+
/// match callsite_enabled() {
416+
/// ALWAYS => on_span(),
417+
/// SOMETIMES => if enabled() { on_span() },
418+
/// NEVER => (),
419+
/// }
420+
/// // for events
421+
/// match callsite_enabled() {
422+
/// ALWAYS => on_event(),
423+
/// SOMETIMES => if enabled() && event_enabled() { on_event() },
424+
/// NEVER => (),
425+
/// }
426+
/// ```
427+
///
428+
/// and an inverted filter defined as:
429+
///
430+
/// ```ignore (pseudo-code)
431+
/// // for spans
432+
/// match callsite_enabled() {
433+
/// ALWAYS => (),
434+
/// SOMETIMES => if !enabled() { on_span() },
435+
/// NEVER => on_span(),
436+
/// }
437+
/// // for events
438+
/// match callsite_enabled() {
439+
/// ALWAYS => (),
440+
/// SOMETIMES => if !enabled() { on_event() },
441+
/// NEVER => on_event(),
442+
/// }
443+
/// ```
444+
///
445+
/// A proper inversion would do `!(enabled() && event_enabled())` (or
446+
/// `!enabled() || !event_enabled()`), but because of the implicit `&&`
447+
/// relation between `enabled` and `event_enabled`, it is difficult to
448+
/// short circuit and not call the wrapped `event_enabled`.
449+
///
450+
/// A combinator which remembers the result of `enabled` in order to call
451+
/// `event_enabled` only when `enabled() == true` is possible, but requires
452+
/// additional thread-local mutable state to support a very niche use case.
453+
//
454+
// Also, it'd mean the wrapped layer's `enabled()` always gets called and
455+
// globally applied to events where it doesn't today, since we can't know
456+
// what `event_enabled` will say until we have the event to call it with.
411457
///
412458
/// [`Filter`]: crate::subscribe::Filter
413459
/// [`enabled`]: crate::subscribe::Filter::enabled

tracing-subscriber/src/filter/subscriber_filters/mod.rs

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,55 @@ pub trait FilterExt<S>: subscribe::Filter<S> {
301301
///
302302
/// This inverts the values returned by the [`enabled`] and [`callsite_enabled`]
303303
/// methods on the wrapped filter; it does *not* invert [`event_enabled`], as
304-
/// implementing that method is optional, and filters which do not implement
305-
/// filtering on event field values will return `true` even for events that their
306-
/// [`enabled`] method would disable.
304+
/// filters which do not implement filtering on event field values will return
305+
/// the default `true` even for events that their [`enabled`] method disables.
306+
///
307+
/// Consider a normal filter defined as:
308+
///
309+
/// ```ignore (pseudo-code)
310+
/// // for spans
311+
/// match callsite_enabled() {
312+
/// ALWAYS => on_span(),
313+
/// SOMETIMES => if enabled() { on_span() },
314+
/// NEVER => (),
315+
/// }
316+
/// // for events
317+
/// match callsite_enabled() {
318+
/// ALWAYS => on_event(),
319+
/// SOMETIMES => if enabled() && event_enabled() { on_event() },
320+
/// NEVER => (),
321+
/// }
322+
/// ```
323+
///
324+
/// and an inverted filter defined as:
325+
///
326+
/// ```ignore (pseudo-code)
327+
/// // for spans
328+
/// match callsite_enabled() {
329+
/// ALWAYS => (),
330+
/// SOMETIMES => if !enabled() { on_span() },
331+
/// NEVER => on_span(),
332+
/// }
333+
/// // for events
334+
/// match callsite_enabled() {
335+
/// ALWAYS => (),
336+
/// SOMETIMES => if !enabled() { on_event() },
337+
/// NEVER => on_event(),
338+
/// }
339+
/// ```
340+
///
341+
/// A proper inversion would do `!(enabled() && event_enabled())` (or
342+
/// `!enabled() || !event_enabled()`), but because of the implicit `&&`
343+
/// relation between `enabled` and `event_enabled`, it is difficult to
344+
/// short circuit and not call the wrapped `event_enabled`.
345+
///
346+
/// A combinator which remembers the result of `enabled` in order to call
347+
/// `event_enabled` only when `enabled() == true` is possible, but requires
348+
/// additional thread-local mutable state to support a very niche use case.
349+
//
350+
// Also, it'd mean the wrapped layer's `enabled()` always gets called and
351+
// globally applied to events where it doesn't today, since we can't know
352+
// what `event_enabled` will say until we have the event to call it with.
307353
///
308354
/// [`Filter`]: crate::subscribe::Filter
309355
/// [`enabled`]: crate::subscribe::Filter::enabled

0 commit comments

Comments
 (0)