moonsignalkit

    Streaming telemetry statistics and change detection for MoonBit.

    signal
    timeseries
    streaming
    telemetry
    cusum
    anomaly-detection
    Download zip
    Author
    Version
    0.3.0
    License
    Apache-2.0
    Last updated
    2 months ago
    Downloads
    27

    #MoonSignalKit

    MoonSignalKit supplies portable time-series and streaming telemetry primitives for MoonBit: batch summaries, bounded rolling quantiles, filters, CSV interchange, online moments, timestamp monitoring, and two-sided CUSUM.

    #Add to a project

    moon add cn-wn/moonsignalkit

    ///|
    test {
    let monitor = TimestampMonitor::new(10)
    let _first = monitor.observe(Sample::new(100, 1.0))
    let observation = monitor.observe(Sample::new(115, 1.0))
    assert_true(observation.is_gap)
    }

    The package has no filesystem, network, browser, or FFI dependency, so its API is shared by Native, JavaScript, Wasm, and Wasm-GC targets. For full examples, quality gates, scope, and related work, see the repository README.

    ChangeDirection

    pub(all) enum ChangeDirection {
    Rising
    Falling
    } derive(Eq,
    Debug
    )

    ChangePoint

    pub(all) struct ChangePoint {
    sample : Sample
    direction : ChangeDirection
    magnitude : Double
    observation : Int
    } derive(
    Debug
    )

    A sustained level shift reported by CusumDetector.

    ChangePoint::to_json

    fn ChangePoint::to_json(self : ChangePoint) -> String

    CsvError

    pub(all) enum CsvError {
    EmptyInput
    MissingColumns(Int)
    InvalidTime(Int)
    InvalidValue(Int)
    } derive(Eq,
    Debug
    )

    Errors reported by the intentionally small, dependency-free telemetry CSV reader.

    The format is two columns: time,value. Quoted fields and locale-specific numeric formats are intentionally out of scope for a portable core library.

    CusumDetector

    pub(all) struct CusumDetector {
    target : Double
    drift : Double
    threshold : Double
    positive_sum : Double
    negative_sum : Double
    observations : Int
    } derive(
    Debug
    )

    Stateful two-sided CUSUM detector for streaming telemetry.

    target is the expected process level, drift suppresses ordinary noise, and threshold controls how much cumulative evidence triggers an event.

    CusumDetector::new

    fn CusumDetector::new(target : Double, drift : Double, threshold : Double) -> CusumDetector

    CusumDetector::push

    fn CusumDetector::push(self : CusumDetector, sample : Sample) -> ChangePoint?

    Processes one sample in O(1) time and returns an event only on a level shift.

    CusumDetector::reset_evidence

    fn CusumDetector::reset_evidence(self : CusumDetector) -> Unit

    Clears accumulated evidence while preserving configuration and count.

    EwmaFilter

    pub(all) struct EwmaFilter {
    alpha : Double
    has_value : Bool
    value : Double
    } derive(
    Debug
    )

    O(1)-memory exponentially weighted moving-average filter.

    EwmaFilter::new

    fn EwmaFilter::new(alpha_per_mille : Int) -> EwmaFilter

    EwmaFilter::push

    fn EwmaFilter::push(self : EwmaFilter, sample : Sample) -> Sample

    EwmaFilter::reset

    fn EwmaFilter::reset(self : EwmaFilter) -> Unit

    EwmaFilter::value

    fn EwmaFilter::value(self : EwmaFilter) -> Double?

    MedianFilter

    pub(all) struct MedianFilter {
    window : RollingWindow
    } derive(
    Debug
    )

    A bounded median filter for suppressing isolated telemetry spikes.

    MedianFilter::new

    fn MedianFilter::new(window : Int) -> MedianFilter

    MedianFilter::push

    fn MedianFilter::push(self : MedianFilter, sample : Sample) -> Sample

    MedianFilter::reset

    fn MedianFilter::reset(self : MedianFilter) -> Unit

    OnlineMoments

    pub(all) struct OnlineMoments {
    count : Int
    mean : Double
    m2 : Double
    min : Double
    max : Double
    } derive(
    Debug
    )

    Numerically stable online statistics using Welford's algorithm.

    Each sample is processed in O(1) time and O(1) memory, so the accumulator can be used for unbounded telemetry streams without retaining raw samples.

    OnlineMoments::new

    OnlineMoments::push

    fn OnlineMoments::push(self : OnlineMoments, value : Double) -> Unit

    Adds one observation using a stable one-pass update.

    OnlineMoments::std_dev

    fn OnlineMoments::std_dev(self : OnlineMoments) -> Double

    OnlineMoments::summary

    fn OnlineMoments::summary(self : OnlineMoments) -> Summary

    Takes an immutable summary without resetting the accumulator.

    OnlineMoments::variance

    fn OnlineMoments::variance(self : OnlineMoments) -> Double

    RollingWindow

    pub(all) struct RollingWindow {
    capacity : Int
    values : Array[Sample]
    size : Int
    next : Int
    } derive(
    Debug
    )

    A bounded chronological telemetry window.

    Appending a sample is O(1). Summaries and quantiles deliberately inspect the bounded window, so their cost is O(window_size) and does not grow with the lifetime of a stream.

    RollingWindow::capacity

    fn RollingWindow::capacity(self : RollingWindow) -> Int

    RollingWindow::is_ready

    fn RollingWindow::is_ready(self : RollingWindow) -> Bool

    RollingWindow::length

    fn RollingWindow::length(self : RollingWindow) -> Int

    RollingWindow::median

    fn RollingWindow::median(self : RollingWindow) -> Double

    RollingWindow::new

    fn RollingWindow::new(capacity : Int) -> RollingWindow

    RollingWindow::push

    fn RollingWindow::push(self : RollingWindow, sample : Sample) -> Unit

    Adds one sample, evicting the oldest sample after the capacity is reached.

    RollingWindow::quantile

    fn RollingWindow::quantile(self : RollingWindow, permille : Int) -> Double

    Returns an exact nearest-rank quantile over the retained values.

    permille is clamped to the inclusive range 0..1000, making 500 the median.

    RollingWindow::reset

    fn RollingWindow::reset(self : RollingWindow) -> Unit

    RollingWindow::samples

    fn RollingWindow::samples(self : RollingWindow) -> Array[Sample]

    Returns retained samples from oldest to newest.

    RollingWindow::summary

    fn RollingWindow::summary(self : RollingWindow) -> Summary

    Computes a numerically stable summary over the current bounded window.

    Sample

    pub(all) struct Sample {
    time : Int
    value : Double
    } derive(
    Debug
    )

    Sample::new

    fn Sample::new(time : Int, value : Double) -> Sample

    Series

    pub(all) struct Series {
    name : String
    samples : Array[Sample]
    } derive(
    Debug
    )

    Series::difference

    fn Series::difference(self : Series, name? : String) -> Series

    Series::exponential_smoothing

    fn Series::exponential_smoothing(self : Series, alpha_per_mille : Int, name? : String) -> Series

    Series::from_csv

    fn Series::from_csv(name : String, csv : String, has_header? : Bool) -> Result[Series, CsvError]

    Imports a two-column time,value CSV document.

    Empty lines are ignored. The first non-empty row is treated as a header when has_header is true, which is the default and matches Series::to_csv.

    Series::is_empty

    fn Series::is_empty(self : Series) -> Bool

    Series::length

    fn Series::length(self : Series) -> Int

    Series::max_value

    fn Series::max_value(self : Series) -> Double

    Series::mean

    fn Series::mean(self : Series) -> Double

    Series::min_value

    fn Series::min_value(self : Series) -> Double

    Series::moving_average

    fn Series::moving_average(self : Series, window : Int, name? : String) -> Series

    Series::new

    fn Series::new(name : String, samples : Array[Sample]) -> Series

    Series::normalize_minmax

    fn Series::normalize_minmax(self : Series, name? : String) -> Series

    Series::outliers

    fn Series::outliers(self : Series, z_threshold : Double) -> Array[Sample]

    Series::peak_count

    fn Series::peak_count(self : Series, threshold : Double) -> Int

    Series::peaks

    fn Series::peaks(self : Series, threshold : Double) -> Array[Sample]

    Series::range

    fn Series::range(self : Series) -> Double

    Series::rate_of_change

    fn Series::rate_of_change(self : Series, name? : String) -> Series

    Series::sum

    fn Series::sum(self : Series) -> Double

    Series::summary

    fn Series::summary(self : Series) -> Summary

    Series::summary_json

    fn Series::summary_json(self : Series) -> String

    Series::to_csv

    fn Series::to_csv(self : Series) -> String

    Exports a series as portable UTF-8 CSV with a time,value header.

    Series::variance

    fn Series::variance(self : Series) -> Double

    Summary

    pub(all) struct Summary {
    count : Int
    min : Double
    max : Double
    mean : Double
    range : Double
    variance : Double
    std_dev : Double
    } derive(
    Debug
    )

    Summary::to_json

    fn Summary::to_json(self : Summary) -> String

    TimestampMonitor

    pub(all) struct TimestampMonitor {
    max_gap : Int
    last_time : Int?
    } derive(
    Debug
    )

    Detects late samples and excessive timestamp gaps without retaining a stream. The latest in-order timestamp is never moved backwards, making observations deterministic for out-of-order telemetry.

    TimestampMonitor::new

    fn TimestampMonitor::new(max_gap : Int) -> TimestampMonitor

    TimestampMonitor::observe

    TimestampMonitor::reset

    fn TimestampMonitor::reset(self : TimestampMonitor) -> Unit

    TimingObservation

    pub(all) struct TimingObservation {
    previous_time : Int?
    time : Int
    delta : Int
    is_late : Bool
    is_gap : Bool
    } derive(
    Debug
    )

    Timing quality observed while accepting one telemetry sample.

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io