1use std::fmt::{Debug, Write};
16use std::sync::atomic::{AtomicU64, Ordering};
17
18use indextree::{Arena, NodeId};
19use itertools::Itertools;
20use parking_lot::{Mutex, MutexGuard};
21
22use crate::root::current_context;
23use crate::Span;
24
25#[derive(Debug, Clone)]
27struct SpanNode {
28 span: Span,
30
31 start_time: coarsetime::Instant,
33}
34
35impl SpanNode {
36 fn new(span: Span) -> Self {
38 Self {
39 span,
40 start_time: coarsetime::Instant::now(),
41 }
42 }
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
53pub(crate) struct ContextId(pub(crate) u64);
54
55#[derive(Debug, Clone)]
57pub struct Tree {
58 arena: Arena<SpanNode>,
60
61 root: NodeId,
63
64 current: NodeId,
66}
67
68#[cfg(feature = "serde")]
69mod serde_impl {
70 use serde::ser::SerializeStruct as _;
71 use serde::Serialize;
72
73 use super::*;
74
75 struct SpanNodeSer<'a> {
76 arena: &'a Arena<SpanNode>,
77 node: NodeId,
78 }
79
80 impl Serialize for SpanNodeSer<'_> {
81 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
82 where
83 S: serde::Serializer,
84 {
85 let inner = self.arena[self.node].get();
86 let mut s = serializer.serialize_struct("Span", 4)?;
87
88 let id: usize = self.node.into();
90 s.serialize_field("id", &id)?;
91 s.serialize_field("span", &inner.span)?;
92 s.serialize_field("elapsed_ns", &inner.start_time.elapsed().as_nanos())?;
93
94 let children = (self.node.children(self.arena))
96 .map(|node| SpanNodeSer {
97 arena: self.arena,
98 node,
99 })
100 .sorted_by_key(|child| {
101 let inner = self.arena[child.node].get();
102 inner.start_time
103 })
104 .collect_vec();
105 s.serialize_field("children", &children)?;
106
107 s.end()
108 }
109 }
110
111 impl Serialize for Tree {
112 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
113 where
114 S: serde::Serializer,
115 {
116 let mut s = serializer.serialize_struct("Tree", 3)?;
117
118 let current_id: usize = self.current.into();
119 s.serialize_field("current", ¤t_id)?;
120
121 s.serialize_field(
123 "tree",
124 &SpanNodeSer {
125 arena: &self.arena,
126 node: self.root,
127 },
128 )?;
129
130 let detached = self
132 .detached_roots()
133 .map(|node| SpanNodeSer {
134 arena: &self.arena,
135 node,
136 })
137 .collect_vec();
138 s.serialize_field("detached", &detached)?;
139
140 s.end()
141 }
142 }
143}
144
145impl std::fmt::Display for Tree {
146 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
147 fn fmt_node(
148 f: &mut std::fmt::Formatter<'_>,
149 arena: &Arena<SpanNode>,
150 node: NodeId,
151 depth: usize,
152 current: NodeId,
153 ) -> std::fmt::Result {
154 f.write_str(&" ".repeat(depth * 2))?;
155
156 let inner = arena[node].get();
157 f.write_str(&inner.span.name)?;
158
159 let elapsed: std::time::Duration = inner.start_time.elapsed().into();
160 write!(
161 f,
162 " [{}{:.3?}]",
163 if !inner.span.is_long_running && elapsed.as_secs() >= 10 {
164 "!!! "
165 } else {
166 ""
167 },
168 elapsed
169 )?;
170
171 if depth > 0 && node == current {
172 f.write_str(" <== current")?;
173 }
174
175 f.write_char('\n')?;
176 for child in node
177 .children(arena)
178 .sorted_by_key(|&id| arena[id].get().start_time)
179 {
180 fmt_node(f, arena, child, depth + 1, current)?;
181 }
182
183 Ok(())
184 }
185
186 fmt_node(f, &self.arena, self.root, 0, self.current)?;
187
188 for node in self.detached_roots() {
190 writeln!(f, "[Detached {node}]")?;
191 fmt_node(f, &self.arena, node, 1, self.current)?;
192 }
193
194 Ok(())
195 }
196}
197
198impl Tree {
199 #[cfg(test)]
201 pub(crate) fn active_node_count(&self) -> usize {
202 self.arena.iter().filter(|n| !n.is_removed()).count()
203 }
204
205 #[cfg(test)]
207 pub(crate) fn detached_node_count(&self) -> usize {
208 self.arena
209 .iter()
210 .filter(|n| {
211 !n.is_removed()
212 && n.parent().is_none()
213 && self.arena.get_node_id(n).unwrap() != self.root
214 })
215 .count()
216 }
217
218 fn detached_roots(&self) -> impl Iterator<Item = NodeId> + '_ {
220 self.arena
221 .iter()
222 .filter(|n| !n.is_removed()) .map(|node| self.arena.get_node_id(node).unwrap()) .filter(|&id| id != self.root && self.arena[id].parent().is_none()) }
226
227 pub(crate) fn push(&mut self, span: Span) -> NodeId {
231 let child = self.arena.new_node(SpanNode::new(span));
232 self.current.prepend(child, &mut self.arena);
233 self.current = child;
234 child
235 }
236
237 pub(crate) fn step_in(&mut self, child: NodeId) {
243 if !self.current.children(&self.arena).contains(&child) {
244 self.current.prepend(child, &mut self.arena);
247 }
248 self.current = child;
249 }
250
251 pub(crate) fn pop(&mut self) {
257 let parent = self.arena[self.current]
258 .parent()
259 .expect("the root node should not be popped");
260 self.remove_and_detach(self.current);
261 self.current = parent;
262 }
263
264 pub(crate) fn step_out(&mut self) {
266 let parent = self.arena[self.current]
267 .parent()
268 .expect("the root node should not be stepped out");
269 self.current = parent;
270 }
271
272 pub(crate) fn remove_and_detach(&mut self, node: NodeId) {
277 node.detach(&mut self.arena);
278 node.remove(&mut self.arena);
280 }
281
282 pub(crate) fn current(&self) -> NodeId {
284 self.current
285 }
286}
287
288#[derive(Debug)]
290pub(crate) struct TreeContext {
291 id: ContextId,
293
294 verbose: bool,
296
297 tree: Mutex<Tree>,
299}
300
301impl TreeContext {
302 pub(crate) fn new(root_span: Span, verbose: bool) -> Self {
304 static ID: AtomicU64 = AtomicU64::new(0);
305 let id = ID.fetch_add(1, Ordering::Relaxed);
306
307 let root_span = root_span.long_running();
309
310 let mut arena = Arena::new();
311 let root = arena.new_node(SpanNode::new(root_span));
312
313 Self {
314 id: ContextId(id),
315 verbose,
316 tree: Tree {
317 arena,
318 root,
319 current: root,
320 }
321 .into(),
322 }
323 }
324
325 pub(crate) fn id(&self) -> ContextId {
327 self.id
328 }
329
330 pub(crate) fn tree(&self) -> MutexGuard<'_, Tree> {
332 self.tree.lock()
333 }
334
335 pub(crate) fn verbose(&self) -> bool {
337 self.verbose
338 }
339}
340
341pub fn current_tree() -> Option<Tree> {
345 current_context().map(|c| c.tree().clone())
346}