Skip to content

Repository files navigation

libspot-rs

libspot-rs

Rust implementations of the SPOT (Streaming Peaks Over Threshold) algorithm for real-time anomaly detection in time series data.

Crate Version Documentation License
libspot (C FFI) Crates.io Documentation License: LGPL v3
libspot-rs (Pure Rust) Crates.io Documentation License: LGPL v3

Installation

Choose your preferred implementation:

# C FFI version (faster, requires C dependencies)
cargo add libspot

# Pure Rust version (safer, no dependencies)
cargo add libspot-rs

Quick Start

Both implementations provide the same core SPOT lifecycle API, so existing fit/step integrations can switch crates by changing the import.

// Choose your implementation:
// use libspot::{SpotDetector, SpotConfig, SpotStatus};      // C FFI version
use libspot_rs::{SpotDetector, SpotConfig, SpotStatus};   // Pure Rust version

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create detector with default configuration
    let config = SpotConfig::default();
    let mut detector = SpotDetector::new(config)?;

    // Fit with training data (normal distribution around 5.0)
    let training_data: Vec<f64> = (0..1000)
        .map(|i| 5.0 + (i as f64 * 0.01).sin() * 2.0)
        .collect();
    detector.fit(&training_data)?;

    // Detect anomalies in real-time
    let test_value = 50.0; // This should be an anomaly
    match detector.step(test_value)? {
        SpotStatus::Normal => println!("Normal data point"),
        SpotStatus::Excess => println!("In the tail distribution"),
        SpotStatus::Anomaly => println!("Anomaly detected! 🚨"),
    }

    Ok(())
}

Configuration

Both implementations support identical configuration:

use libspot_rs::SpotConfig; // or use libspot::SpotConfig;

let config = SpotConfig {
    q: 0.0001,              // Anomaly probability threshold (lower = more sensitive)
    low_tail: false,        // Monitor upper tail (set true for lower tail)
    discard_anomalies: true, // Exclude anomalies from model updates
    level: 0.998,           // Quantile level that defines the tail
    max_excess: 200,        // Maximum number of excess values to store
};

Comparison

Feature libspot (C FFI) libspot-rs (Pure Rust)
Installation cargo add libspot cargo add libspot-rs
Type C FFI Bindings Pure Rust Implementation
Core API ✅ Reference API ✅ Compatible
Performance ~1.55 s (50M samples) ~1.19 s (50M samples)
Memory Safety ⚠️ Manual (C code) ✅ Guaranteed
Dependencies 📦 C library + bindgen 🎯 None
Cross-platform ⚠️ Build complexity ✅ Easy
WebAssembly ❌ Limited support ✅ Full support
Results Matches C 3.1.0 Matches C 3.1.0 in consistency tests
Key Benefits Fast, Proven, Compatible Safe, Portable, WebAssembly
Documentation docs.rs/libspot docs.rs/libspot-rs

Correctness & Performance

libspot 3.1.0 bundles upstream C 3.1.0. Both it and libspot-rs 0.4.0-rc.3 include the P² extrema marker fix from upstream #42. Refitting models can produce different thresholds and classifications than earlier versions.

CI compares C, Rust FFI, and pure Rust directly: anomaly/excess/normal counts and thresholds must match to the printed precision. It then benchmarks all three binaries on 50M samples. See the workflow run summaries for current results and timings (Linux x86_64, release builds, hyperfine --warmup 1 --runs 5).

Benchmark Commands:

  • Pure Rust: cargo run -p libspot-rs -r --example basic_pure
  • C FFI: cargo run -p libspot -r --example basic_ffi
  • Original C: cd crates/libspot/libspot && make && cc -O3 -o /tmp/basic ../examples/basic.c dist/libspot.a.$(cat version) -Idist/ -lm && /tmp/basic

Documentation

Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.

The repository is a Cargo workspace with three members:

  • libspot: the C FFI wrapper and its tests.
  • libspot-rs: the pure Rust implementation and its tests.
  • libspot-compat-tests: cross-implementation tests and comparison examples; this package is not published.

All members share the root Cargo.lock and target/ directory. From the repository root, run:

# Run tests for every workspace member (also the default for cargo test here).
cargo test --workspace --locked

# Run one package, including pure Rust without its default features.
cargo test -p libspot-rs --no-default-features --locked
cargo test -p libspot-compat-tests --locked

# Check all members and run a comparison example.
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
cargo run -p libspot-compat-tests --release --example compare_implementations --locked

License

This project is licensed under the GNU Lesser General Public License v3.0 (LGPL-3.0) to comply with the underlying libspot C library license.

Acknowledgments

The logo design is adapted from the original libspot logo with Rust-themed styling to reflect this project's implementation in the Rust programming language.

About

A Rust wrapper for the libspot

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages