use crate::layer::CallTreeLayer;
use crate::snapshot::CallTreeSnapshot;
use crate::tree::CallTreeState;
use std::fmt;
use std::sync::Arc;
use tracing::Metadata;
pub(crate) const DEFAULT_WINDOW_SIZE: usize = 100;
pub(crate) const DEFAULT_MAX_NODES: usize = 10_000;
pub(crate) const DEFAULT_MAX_DEPTH: usize = 64;
type MetadataFilter = dyn for<'a> Fn(&Metadata<'a>) -> bool + Send + Sync + 'static;
pub(crate) struct Config {
pub(crate) window_size: usize,
pub(crate) max_nodes: usize,
pub(crate) max_depth: usize,
pub(crate) filter: Arc<MetadataFilter>,
}
pub(crate) struct CallTreeInner {
pub(crate) config: Config,
pub(crate) state: CallTreeState,
}
#[derive(Clone)]
pub struct CallTree {
pub(crate) inner: Arc<CallTreeInner>,
}
impl CallTree {
pub fn new() -> Self {
Self::builder().build()
}
pub fn builder() -> CallTreeBuilder {
CallTreeBuilder::default()
}
pub fn layer(&self) -> CallTreeLayer {
CallTreeLayer::new(self.inner.clone())
}
pub fn snapshot(&self) -> CallTreeSnapshot {
self.inner.state.snapshot()
}
pub fn internal_stats(&self) -> InternalStats {
InternalStats {
nodes: self.inner.state.node_count(),
rejected_nodes: self.inner.state.rejected_nodes(),
dropped_samples: self.inner.state.dropped_samples(),
}
}
}
impl Default for CallTree {
fn default() -> Self {
Self::new()
}
}
pub struct CallTreeBuilder {
window_size: usize,
max_nodes: usize,
max_depth: usize,
filter: Arc<MetadataFilter>,
}
impl Default for CallTreeBuilder {
fn default() -> Self {
Self {
window_size: DEFAULT_WINDOW_SIZE,
max_nodes: DEFAULT_MAX_NODES,
max_depth: DEFAULT_MAX_DEPTH,
filter: Arc::new(|_| true),
}
}
}
impl fmt::Debug for CallTreeBuilder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CallTreeBuilder")
.field("window_size", &self.window_size)
.field("max_nodes", &self.max_nodes)
.field("max_depth", &self.max_depth)
.finish_non_exhaustive()
}
}
impl CallTreeBuilder {
pub fn window_size(mut self, window_size: usize) -> Self {
self.window_size = window_size;
self
}
pub fn max_nodes(mut self, max_nodes: usize) -> Self {
self.max_nodes = max_nodes;
self
}
pub fn max_depth(mut self, max_depth: usize) -> Self {
self.max_depth = max_depth;
self
}
pub fn filter<F>(mut self, filter: F) -> Self
where
F: for<'a> Fn(&Metadata<'a>) -> bool + Send + Sync + 'static,
{
self.filter = Arc::new(filter);
self
}
pub fn build(self) -> CallTree {
CallTree {
inner: Arc::new(CallTreeInner {
config: Config {
window_size: self.window_size,
max_nodes: self.max_nodes,
max_depth: self.max_depth,
filter: self.filter,
},
state: CallTreeState::default(),
}),
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub struct InternalStats {
pub nodes: usize,
pub rejected_nodes: u64,
pub dropped_samples: u64,
}