tracing_timing/
group.rs

1//! Commonly used span and event grouping mechanisms.
2
3use super::EventGroup;
4use super::SpanGroup;
5use std::borrow::Cow;
6use std::fmt::Write;
7use tracing_core::*;
8
9impl<F, R> SpanGroup for F
10where
11    F: Fn(&span::Attributes) -> R,
12{
13    type Id = R;
14    fn group(&self, a: &span::Attributes) -> Self::Id {
15        (self)(a)
16    }
17}
18
19impl<F, R> EventGroup for F
20where
21    F: Fn(&Event) -> R,
22{
23    type Id = R;
24    fn group(&self, e: &Event) -> Self::Id {
25        (self)(e)
26    }
27}
28
29/// Group spans/events by their configured `target`.
30///
31/// This is usually the module path where the span or event was created.
32/// See `Metadata::target` in `tracing` for details.
33#[derive(Default, Clone, Copy, Debug, Eq, PartialEq)]
34pub struct ByTarget;
35
36impl SpanGroup for ByTarget {
37    type Id = &'static str;
38    fn group(&self, a: &span::Attributes) -> Self::Id {
39        a.metadata().target()
40    }
41}
42
43impl EventGroup for ByTarget {
44    type Id = &'static str;
45    fn group(&self, e: &Event) -> Self::Id {
46        e.metadata().target()
47    }
48}
49
50/// Group spans/events by their "name".
51///
52/// For spans, this is the string passed as the first argument to the various span tracing macros.
53/// For events, this is usually the source file and line number where the event was created.
54#[derive(Default, Clone, Copy, Debug, Eq, PartialEq)]
55pub struct ByName;
56
57impl SpanGroup for ByName {
58    type Id = &'static str;
59    fn group(&self, a: &span::Attributes) -> Self::Id {
60        a.metadata().name()
61    }
62}
63
64impl EventGroup for ByName {
65    type Id = &'static str;
66    fn group(&self, e: &Event) -> Self::Id {
67        e.metadata().name()
68    }
69}
70
71/// Group events by their "message".
72///
73/// This is the string passed as the first argument to the various event tracing macros.
74#[derive(Default, Clone, Copy, Debug, Eq, PartialEq)]
75pub struct ByMessage;
76
77impl EventGroup for ByMessage {
78    type Id = String;
79    fn group(&self, e: &Event) -> Self::Id {
80        EventGroup::group(&ByField(Cow::Borrowed("message")), e)
81    }
82}
83
84/// Group spans/events by the value of a particular field.
85///
86/// If a field by the contained name is found, its recorded value (usually its `Debug` value) is
87/// used as the grouping identifier. If the field is not found, an empty `String` is used.
88#[derive(Default, Clone, Debug, Eq, PartialEq)]
89pub struct ByField(pub Cow<'static, str>);
90
91impl<T> From<T> for ByField
92where
93    T: Into<Cow<'static, str>>,
94{
95    fn from(t: T) -> Self {
96        Self(t.into())
97    }
98}
99
100struct ByFieldVisitor<'a> {
101    field: &'a ByField,
102    value: String,
103}
104
105impl<'a> field::Visit for ByFieldVisitor<'a> {
106    fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) {
107        if field.name() == &*self.field.0 {
108            write!(&mut self.value, "{:?}", value).unwrap();
109        }
110    }
111
112    fn record_i64(&mut self, field: &Field, value: i64) {
113        if field.name() == &*self.field.0 {
114            write!(&mut self.value, "{}", value).unwrap();
115        }
116    }
117
118    fn record_u64(&mut self, field: &Field, value: u64) {
119        if field.name() == &*self.field.0 {
120            write!(&mut self.value, "{}", value).unwrap();
121        }
122    }
123
124    fn record_str(&mut self, field: &Field, value: &str) {
125        if field.name() == &*self.field.0 {
126            write!(&mut self.value, "{}", value).unwrap();
127        }
128    }
129}
130
131impl SpanGroup for ByField {
132    type Id = String;
133    fn group(&self, a: &span::Attributes) -> Self::Id {
134        let mut visitor = ByFieldVisitor {
135            field: self,
136            value: String::new(),
137        };
138        a.record(&mut visitor);
139        visitor.value
140    }
141}
142
143impl EventGroup for ByField {
144    type Id = String;
145    fn group(&self, e: &Event) -> Self::Id {
146        let mut visitor = ByFieldVisitor {
147            field: self,
148            value: String::new(),
149        };
150        e.record(&mut visitor);
151        visitor.value
152    }
153}