Skip to main content

anomstream_core/thresholded/
mod.rs

1//! Adaptive-threshold layer on top of [`crate::RandomCutForest`].
2//!
3//! Where the bare forest returns a raw anomaly score in `[0, ∞)`,
4//! [`ThresholdedForest`] tracks the running distribution of those
5//! scores and emits a graded verdict — `is_anomaly: bool`,
6//! `grade ∈ [0, 1]`, and the `threshold` in effect at observation
7//! time. Callers no longer have to hand-pick a magic threshold per
8//! deployment: the detector adapts to the traffic it sees.
9//!
10//! Inspired by the AWS *Thresholded Random Cut Forest* (TRCF)
11//! facility in `randomcutforest-parkservices`, but intentionally
12//! lighter: only the adaptive μ + z·σ threshold over an EMA of the
13//! score stream, without the short/long-term duality or the
14//! near-threshold heuristics of the full TRCF.
15//!
16//! # Example
17//!
18//! ```ignore
19//! use anomstream_core::ThresholdedForestBuilder;
20//!
21//! let mut detector = ThresholdedForestBuilder::<4>::new()
22//!     .num_trees(100)
23//!     .sample_size(256)
24//!     .z_factor(3.0)
25//!     .min_observations(32)
26//!     .seed(42)
27//!     .build()?;
28//!
29//! for packet in stream_of_feature_vectors {
30//!     let verdict = detector.process(packet)?;
31//!     if verdict.is_anomaly() {
32//!         eprintln!(
33//!             "anomaly: grade={:.2} score={} threshold={:.3}",
34//!             verdict.grade(),
35//!             verdict.score(),
36//!             verdict.threshold(),
37//!         );
38//!     }
39//! }
40//! # Ok::<(), anomstream_core::RcfError>(())
41//! ```
42
43pub mod config;
44pub mod detector;
45pub mod grade;
46pub mod stats;
47
48pub use config::{
49    DEFAULT_MIN_OBSERVATIONS, DEFAULT_MIN_THRESHOLD, DEFAULT_QUANTILE, DEFAULT_SCORE_DECAY,
50    DEFAULT_Z_FACTOR, ThresholdMode, ThresholdedConfig, ThresholdedForestBuilder,
51};
52pub use detector::ThresholdedForest;
53pub use grade::AnomalyGrade;
54pub use stats::EmaStats;