Skip to main content

tracing_calltree/
builder.rs

1use 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}