1use super::*;
2use hdrhistogram::SyncHistogram;
3use indexmap::IndexMap;
4use std::hash::Hash;
5use std::sync::atomic;
6
7pub struct TimingLayer<S = group::ByName, E = group::ByMessage>
14where
15 S: SpanGroup,
16 S::Id: Hash + Eq,
17 E: EventGroup,
18 E::Id: Hash + Eq,
19{
20 timing: Timing<S, E>,
21}
22
23impl<S, E> std::fmt::Debug for TimingLayer<S, E>
24where
25 S: SpanGroup + std::fmt::Debug,
26 S::Id: Hash + Eq + std::fmt::Debug,
27 E: EventGroup + std::fmt::Debug,
28 E::Id: Hash + Eq + std::fmt::Debug,
29{
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 f.debug_struct("TimingLayer")
32 .field("timing", &self.timing)
33 .finish()
34 }
35}
36
37impl<S, E> TimingLayer<S, E>
38where
39 S: SpanGroup,
40 E: EventGroup,
41 S::Id: Hash + Eq,
42 E::Id: Hash + Eq,
43{
44 pub(crate) fn new(timing: Timing<S, E>) -> Self {
45 Self { timing }
46 }
47
48 pub fn force_synchronize(&self) {
52 self.timing.force_synchronize()
53 }
54
55 pub fn with_histograms<F, R>(&self, f: F) -> R
66 where
67 F: FnOnce(&mut HashMap<S::Id, IndexMap<E::Id, SyncHistogram<u64>, Hasher>>) -> R,
68 {
69 self.timing.with_histograms(f)
70 }
71}
72
73impl<S, SG, EG> tracing_subscriber::Layer<S> for TimingLayer<SG, EG>
74where
75 S: Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span>,
76 Self: 'static,
77 SG: SpanGroup,
78 EG: EventGroup,
79 SG::Id: Clone + Hash + Eq + Send + Sync,
80 EG::Id: Clone + Hash + Eq + Send + Sync,
81{
82 fn on_new_span(
83 &self,
84 attrs: &span::Attributes,
85 id: &span::Id,
86 ctx: tracing_subscriber::layer::Context<S>,
87 ) {
88 let group = self.timing.span_group.group(attrs);
89 self.timing.ensure_group(group.clone());
90 let span = ctx.span(id).unwrap();
91 span.extensions_mut().insert(SpanState {
92 group,
93 last_event: atomic::AtomicU64::new(self.timing.time.raw()),
94 });
95 }
96
97 fn on_event(&self, event: &Event, ctx: tracing_subscriber::layer::Context<S>) {
98 let span = event
99 .parent()
100 .cloned()
101 .or_else(|| ctx.current_span().id().cloned());
102 if let Some(id) = span {
103 let current = ctx.span(&id);
104 self.timing.time(event, |on_each| {
105 if let Some(ref span) = current {
106 {
107 let ext = span.extensions();
108 if !on_each(ext.get::<SpanState<SG::Id>>().unwrap()) {
109 return;
110 }
111 }
112
113 for span in span.scope().skip(1) {
114 let ext = span.extensions();
115 if !on_each(ext.get::<SpanState<SG::Id>>().unwrap()) {
116 break;
117 }
118 }
119 }
120 });
121 } else {
122 }
124 }
125
126 fn on_close(&self, id: span::Id, ctx: tracing_subscriber::layer::Context<'_, S>) {
127 if self.timing.span_close_events {
128 let span = ctx.span(&id).expect("Span not found, this is a bug");
129 let meta = span.metadata();
130 let fs = field::FieldSet::new(&["message"], meta.callsite());
131 let fld = fs.iter().next().unwrap();
132 let v = [(&fld, Some(&"close" as &dyn field::Value))];
133 let vs = fs.value_set(&v);
134 let e = Event::new_child_of(id, meta, &vs);
135 self.timing.time(&e, |on_each| {
136 {
137 let ext = span.extensions();
138 if !on_each(ext.get::<SpanState<SG::Id>>().unwrap()) {
139 return;
140 }
141 }
142
143 for span in span.scope().skip(1) {
144 let ext = span.extensions();
145 if !on_each(ext.get::<SpanState<SG::Id>>().unwrap()) {
146 break;
147 }
148 }
149 });
150 }
151 }
152}
153
154#[derive(Debug, Copy)]
158pub struct Downcaster<S, E> {
159 phantom: PhantomData<fn(S, E)>,
160}
161
162impl<S, E> Clone for Downcaster<S, E> {
163 fn clone(&self) -> Self {
164 Self {
165 phantom: PhantomData,
166 }
167 }
168}
169
170impl<S, E> TimingLayer<S, E>
171where
172 S: SpanGroup,
173 E: EventGroup,
174 S::Id: Clone + Hash + Eq,
175 E::Id: Clone + Hash + Eq,
176{
177 pub fn downcaster(&self) -> Downcaster<S, E> {
205 Downcaster {
206 phantom: PhantomData,
207 }
208 }
209}
210
211impl<S, E> Downcaster<S, E>
212where
213 S: SpanGroup + 'static,
214 E: EventGroup + 'static,
215 S::Id: Clone + Hash + Eq + 'static,
216 E::Id: Clone + Hash + Eq + 'static,
217{
218 pub fn downcast<'a>(&self, d: &'a Dispatch) -> Option<&'a TimingLayer<S, E>> {
223 d.downcast_ref()
224 }
225}