1use ::daggy::Dag;
2use ::tracing::span;
3use ::tracing::{Event, Metadata};
4use indexmap::IndexMap;
5use once_cell::sync::Lazy;
6use tracing_subscriber::layer::Context;
7use tracing_subscriber::registry::LookupSpan;
8
9use crate::log::LogsRecorder;
10use crate::record::Recorder;
11use crate::report::ALL_DAGS;
12use crate::LazyMutex;
13
14pub(crate) static ALL_SPANS: LazyMutex<IndexMap<u64, Recorder>> = Lazy::new(Default::default);
15pub(crate) static ALL_LOGS: LazyMutex<LogsRecorder> = Lazy::new(Default::default);
16pub(crate) static SPAN_ID_TO_ROOT_AND_NODE_INDEX: LazyMutex<
17 IndexMap<u64, (u64, daggy::NodeIndex)>,
18> = Lazy::new(Default::default);
19
20#[derive(Debug, Default)]
21pub struct Layer {}
22
23impl Layer {
24 fn record(&self, id: span::Id, record: &span::Record<'_>) {
25 ALL_SPANS
26 .lock()
27 .unwrap()
28 .get_mut(&id.into_u64())
29 .unwrap_or_else(|| panic!("no record for id {}", id.into_u64()))
30 .record(record);
31 }
32
33 fn event(&self, event: &Event<'_>, ctx: Context<'_, impl tracing::Subscriber>) {
34 let current_span = ctx.current_span();
35 let current_span = current_span.id().cloned();
36 ALL_LOGS.lock().unwrap().event(current_span, event);
37 }
38
39 fn attributes(
40 &self,
41 span_id: span::Id,
42 attributes: &span::Attributes<'_>,
43 parent_id: Option<span::Id>,
44 ) {
45 let raw_span_id = span_id.into_u64();
46
47 if let Some(id) = parent_id {
48 let raw_parent_id = id.into_u64();
50
51 let mut id_to_node_index = SPAN_ID_TO_ROOT_AND_NODE_INDEX.lock().unwrap();
52
53 let (root_span_id, parent_node_index) = id_to_node_index
54 .get(&raw_parent_id)
55 .copied()
56 .unwrap_or_else(|| panic!("missing parent attributes for {}.", raw_parent_id));
57
58 let (_, node_index) =
59 if let Some(span_dag) = ALL_DAGS.lock().unwrap().get_mut(&root_span_id) {
60 span_dag.add_child(parent_node_index, (), raw_span_id)
61 } else {
62 panic!("missing dag for root {}", root_span_id);
63 };
64
65 id_to_node_index.insert(raw_span_id, (root_span_id, node_index));
66 } else {
67 let mut new_dag: Dag<u64, ()> = Default::default();
69 let root_index = new_dag.add_node(raw_span_id);
70
71 SPAN_ID_TO_ROOT_AND_NODE_INDEX
73 .lock()
74 .unwrap()
75 .insert(raw_span_id, (raw_span_id, root_index));
76
77 let mut all_dags = ALL_DAGS.lock().unwrap();
78 all_dags.insert(raw_span_id, new_dag);
79 }
80
81 ALL_SPANS
82 .lock()
83 .unwrap()
84 .entry(raw_span_id)
85 .or_default()
86 .attributes(span_id, attributes);
87 }
88}
89
90impl<S> tracing_subscriber::Layer<S> for Layer
91where
92 S: tracing::Subscriber + for<'lookup> LookupSpan<'lookup>,
93{
94 fn register_callsite(
95 &self,
96 _metadata: &'static Metadata<'static>,
97 ) -> tracing::subscriber::Interest {
98 tracing::subscriber::Interest::always()
99 }
100
101 fn on_new_span(
102 &self,
103 attrs: &span::Attributes<'_>,
104 id: &span::Id,
105 ctx: tracing_subscriber::layer::Context<'_, S>,
106 ) {
107 let maybe_parent_id = attrs
108 .parent()
109 .cloned()
110 .or_else(|| ctx.current_span().id().cloned());
111
112 self.attributes(id.clone(), attrs, maybe_parent_id)
113 }
114
115 fn on_record(
116 &self,
117 span: &span::Id,
118 values: &span::Record<'_>,
119 _ctx: tracing_subscriber::layer::Context<'_, S>,
120 ) {
121 self.record(span.clone(), values)
122 }
123
124 fn on_event(&self, event: &Event<'_>, ctx: tracing_subscriber::layer::Context<'_, S>) {
125 self.event(event, ctx)
126 }
127}