tracing_capture/predicates/
name.rs

1//! `name()` predicate factory.
2
3use predicates::{
4    reflection::{Case, PredicateReflection},
5    Predicate,
6};
7
8use std::fmt;
9
10use crate::CapturedSpan;
11
12/// Creates a predicate for the name of a [`CapturedSpan`].
13///
14/// # Arguments
15///
16/// The argument of this function can be any `str`ing predicate, e.g. `eq("test")` for
17/// exact comparison.
18///
19/// # Examples
20///
21/// ```
22/// # use predicates::{ord::eq, str::starts_with};
23/// # use tracing_subscriber::{layer::SubscriberExt, Registry};
24/// # use tracing_capture::{predicates::{name, ScanExt}, CaptureLayer, SharedStorage};
25/// let storage = SharedStorage::default();
26/// let subscriber = Registry::default().with(CaptureLayer::new(&storage));
27/// tracing::subscriber::with_default(subscriber, || {
28///     tracing::info_span!("compute").in_scope(|| {
29///         tracing::info!(answer = 42, "done");
30///     });
31/// });
32///
33/// let storage = storage.lock();
34/// // All of these access the single captured span.
35/// let spans = storage.scan_spans();
36/// let _ = spans.single(&name(eq("compute")));
37/// let _ = spans.single(&name(starts_with("co")));
38/// ```
39pub fn name<P: Predicate<str>>(matches: P) -> NamePredicate<P> {
40    NamePredicate { matches }
41}
42
43/// Predicate for the name of a [`CapturedSpan`] returned by the [`name()`] function.
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45pub struct NamePredicate<P> {
46    matches: P,
47}
48
49impl_bool_ops!(NamePredicate<P>);
50
51impl<P: Predicate<str>> fmt::Display for NamePredicate<P> {
52    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
53        write!(formatter, "name({})", self.matches)
54    }
55}
56
57impl<P: Predicate<str>> PredicateReflection for NamePredicate<P> {}
58
59impl<P: Predicate<str>> Predicate<CapturedSpan<'_>> for NamePredicate<P> {
60    fn eval(&self, variable: &CapturedSpan<'_>) -> bool {
61        self.matches.eval(variable.metadata().name())
62    }
63
64    fn find_case(&self, expected: bool, variable: &CapturedSpan<'_>) -> Option<Case<'_>> {
65        let child = self
66            .matches
67            .find_case(expected, variable.metadata().name())?;
68        Some(Case::new(Some(self), expected).add_child(child))
69    }
70}