tracing_calltree/
builder.rs1use crate::layer::CallTreeLayer;
2use crate::snapshot::CallTreeSnapshot;
3use crate::tree::CallTreeState;
4use std::fmt;
5use std::sync::Arc;
6use tracing::Metadata;
7
8pub(crate) const DEFAULT_WINDOW_SIZE: usize = 100;
9pub(crate) const DEFAULT_MAX_NODES: usize = 10_000;
10pub(crate) const DEFAULT_MAX_DEPTH: usize = 64;
11
12type MetadataFilter = dyn for<'a> Fn(&Metadata<'a>) -> bool + Send + Sync + 'static;
13
14pub(crate) struct Config {
15 pub(crate) window_size: usize,
16 pub(crate) max_nodes: usize,
17 pub(crate) max_depth: usize,
18 pub(crate) filter: Arc<MetadataFilter>,
19}
20
21pub(crate) struct CallTreeInner {
22 pub(crate) config: Config,
23 pub(crate) state: CallTreeState,
24}
25
26#[derive(Clone)]
27pub struct CallTree {
28 pub(crate) inner: Arc<CallTreeInner>,
29}
30
31impl CallTree {
32 pub fn new() -> Self {
33 Self::builder().build()
34 }
35
36 pub fn builder() -> CallTreeBuilder {
37 CallTreeBuilder::default()
38 }
39
40 pub fn layer(&self) -> CallTreeLayer {
41 CallTreeLayer::new(self.inner.clone())
42 }
43
44 pub fn snapshot(&self) -> CallTreeSnapshot {
45 self.inner.state.snapshot()
46 }
47
48 pub fn internal_stats(&self) -> InternalStats {
49 InternalStats {
50 nodes: self.inner.state.node_count(),
51 rejected_nodes: self.inner.state.rejected_nodes(),
52 dropped_samples: self.inner.state.dropped_samples(),
53 }
54 }
55}
56
57impl Default for CallTree {
58 fn default() -> Self {
59 Self::new()
60 }
61}
62
63pub struct CallTreeBuilder {
64 window_size: usize,
65 max_nodes: usize,
66 max_depth: usize,
67 filter: Arc<MetadataFilter>,
68}
69
70impl Default for CallTreeBuilder {
71 fn default() -> Self {
72 Self {
73 window_size: DEFAULT_WINDOW_SIZE,
74 max_nodes: DEFAULT_MAX_NODES,
75 max_depth: DEFAULT_MAX_DEPTH,
76 filter: Arc::new(|_| true),
77 }
78 }
79}
80
81impl fmt::Debug for CallTreeBuilder {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 f.debug_struct("CallTreeBuilder")
84 .field("window_size", &self.window_size)
85 .field("max_nodes", &self.max_nodes)
86 .field("max_depth", &self.max_depth)
87 .finish_non_exhaustive()
88 }
89}
90
91impl CallTreeBuilder {
92 pub fn window_size(mut self, window_size: usize) -> Self {
93 self.window_size = window_size;
94 self
95 }
96
97 pub fn max_nodes(mut self, max_nodes: usize) -> Self {
98 self.max_nodes = max_nodes;
99 self
100 }
101
102 pub fn max_depth(mut self, max_depth: usize) -> Self {
103 self.max_depth = max_depth;
104 self
105 }
106
107 pub fn filter<F>(mut self, filter: F) -> Self
108 where
109 F: for<'a> Fn(&Metadata<'a>) -> bool + Send + Sync + 'static,
110 {
111 self.filter = Arc::new(filter);
112 self
113 }
114
115 pub fn build(self) -> CallTree {
116 CallTree {
117 inner: Arc::new(CallTreeInner {
118 config: Config {
119 window_size: self.window_size,
120 max_nodes: self.max_nodes,
121 max_depth: self.max_depth,
122 filter: self.filter,
123 },
124 state: CallTreeState::default(),
125 }),
126 }
127 }
128}
129
130#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
131#[cfg_attr(feature = "serde", derive(serde::Serialize))]
132#[non_exhaustive]
133pub struct InternalStats {
134 pub nodes: usize,
135 pub rejected_nodes: u64,
136 pub dropped_samples: u64,
137}