tracing_capture/predicates/
parent.rs

1//! `parent()` predicate factory.
2
3use predicates::{
4    reflection::{Case, PredicateReflection, Product},
5    Predicate,
6};
7
8use std::{fmt, iter};
9
10use crate::{Captured, CapturedSpan};
11
12/// Creates a predicate for the direct parent [`CapturedSpan`] of a span or a [`CapturedEvent`].
13///
14/// [`CapturedEvent`]: crate::CapturedEvent
15///
16/// # Examples
17///
18/// ```
19/// # use predicates::ord::eq;
20/// # use tracing_core::Level;
21/// # use tracing_subscriber::{layer::SubscriberExt, Registry};
22/// # use tracing_capture::{predicates::*, CaptureLayer, SharedStorage};
23/// let storage = SharedStorage::default();
24/// let subscriber = Registry::default().with(CaptureLayer::new(&storage));
25/// tracing::subscriber::with_default(subscriber, || {
26///     tracing::info_span!("compute").in_scope(|| {
27///         tracing::info!(answer = 42, "done");
28///     });
29/// });
30///
31/// let storage = storage.lock();
32/// let parent_pred = level(Level::INFO) & name(eq("compute"));
33/// let _ = storage.scan_events().single(&parent(parent_pred));
34/// ```
35pub fn parent<P>(matches: P) -> ParentPredicate<P>
36where
37    P: for<'a> Predicate<CapturedSpan<'a>>,
38{
39    ParentPredicate { matches }
40}
41
42/// Predicate for the parent of a [`CapturedSpan`] or [`CapturedEvent`] returned
43/// by the [`parent()`] function.
44///
45/// [`CapturedEvent`]: crate::CapturedEvent
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub struct ParentPredicate<P> {
48    matches: P,
49}
50
51impl_bool_ops!(ParentPredicate<P>);
52
53impl<P> fmt::Display for ParentPredicate<P>
54where
55    P: for<'a> Predicate<CapturedSpan<'a>>,
56{
57    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
58        write!(formatter, "parent({})", self.matches)
59    }
60}
61
62impl<P> PredicateReflection for ParentPredicate<P> where P: for<'a> Predicate<CapturedSpan<'a>> {}
63
64impl<'a, P, T> Predicate<T> for ParentPredicate<P>
65where
66    T: Captured<'a>,
67    P: for<'p> Predicate<CapturedSpan<'p>>,
68{
69    fn eval(&self, variable: &T) -> bool {
70        let parent = variable.parent();
71        parent.map_or(false, |parent| self.matches.eval(&parent))
72    }
73
74    fn find_case(&self, expected: bool, variable: &T) -> Option<Case<'_>> {
75        let parent = variable.parent();
76        let parent = if let Some(parent) = parent {
77            parent
78        } else {
79            return if expected {
80                None // was expecting a parent, but there is none
81            } else {
82                let product = Product::new("parent", "None");
83                Some(Case::new(Some(self), expected).add_product(product))
84            };
85        };
86
87        let child = self.matches.find_case(expected, &parent)?;
88        Some(Case::new(Some(self), expected).add_child(child))
89    }
90}
91
92/// Creates a predicate for ancestor [`CapturedSpan`]s of a span or a [`CapturedEvent`].
93/// The predicate is true iff the wrapped span predicate holds true for *any* of the ancestors.
94///
95/// [`CapturedEvent`]: crate::CapturedEvent
96///
97/// # Examples
98///
99/// ```
100/// # use predicates::ord::eq;
101/// # use tracing_core::Level;
102/// # use tracing_subscriber::{layer::SubscriberExt, Registry};
103/// # use tracing_capture::{predicates::*, CaptureLayer, SharedStorage};
104/// let storage = SharedStorage::default();
105/// let subscriber = Registry::default().with(CaptureLayer::new(&storage));
106/// tracing::subscriber::with_default(subscriber, || {
107///     let _entered = tracing::info_span!("wrapper").entered();
108///     tracing::info_span!("compute").in_scope(|| {
109///         tracing::info!(answer = 42, "done");
110///     });
111/// });
112///
113/// let storage = storage.lock();
114/// let parent_pred = level(Level::INFO) & name(eq("wrapper"));
115/// let _ = storage.scan_events().single(&ancestor(parent_pred));
116/// ```
117pub fn ancestor<P>(matches: P) -> AncestorPredicate<P>
118where
119    P: for<'a> Predicate<CapturedSpan<'a>>,
120{
121    AncestorPredicate { matches }
122}
123
124/// Predicate for the ancestors of a [`CapturedSpan`] or [`CapturedEvent`] returned
125/// by the [`ancestor()`] function.
126///
127/// [`CapturedEvent`]: crate::CapturedEvent
128#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129pub struct AncestorPredicate<P> {
130    matches: P,
131}
132
133impl_bool_ops!(AncestorPredicate<P>);
134
135impl<P> fmt::Display for AncestorPredicate<P>
136where
137    P: for<'a> Predicate<CapturedSpan<'a>>,
138{
139    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
140        write!(formatter, "ancestor({})", self.matches)
141    }
142}
143
144impl<P> PredicateReflection for AncestorPredicate<P> where P: for<'a> Predicate<CapturedSpan<'a>> {}
145
146impl<'a, P, T> Predicate<T> for AncestorPredicate<P>
147where
148    T: Captured<'a>,
149    P: for<'p> Predicate<CapturedSpan<'p>>,
150{
151    fn eval(&self, variable: &T) -> bool {
152        let mut ancestors = iter::successors(variable.parent(), CapturedSpan::parent);
153        ancestors.any(|span| self.matches.eval(&span))
154    }
155
156    fn find_case(&self, expected: bool, variable: &T) -> Option<Case<'_>> {
157        let mut ancestors = iter::successors(variable.parent(), CapturedSpan::parent);
158        if expected {
159            // Return the first of ancestor cases.
160            let child = ancestors.find_map(|span| self.matches.find_case(expected, &span))?;
161            Some(Case::new(Some(self), expected).add_child(child))
162        } else {
163            // Need all ancestor cases.
164            let case = Case::new(Some(self), expected);
165            ancestors.try_fold(case, |case, span| {
166                let child = self.matches.find_case(expected, &span)?;
167                Some(case.add_child(child))
168            })
169        }
170    }
171}