All pastes #9GkN25dHc6 Raw Edit

Hew metrics aggregation demo

public hew v1 · immutable
#9GkN25dHc6 ·published 2026-06-11 04:02 UTC ·by slepp
rendered paste body
//! A small metrics aggregation service: sources push samples to a//! collector actor, a periodic ticker counts snapshots, and asks read//! the aggregates back out.type Sample {    name: string;    value: f64;}actor Collector {    var counts: HashMap<string, i64> = HashMap::new();    var sums: HashMap<string, f64> = HashMap::new();    var snapshots_taken: i64 = 0;    receive fn observe(name: string, value: f64) {        let prior_count = match counts.get(name) {            Some(c) => c,            None => 0,        };        counts.insert(name, prior_count + 1);        let prior_sum = match sums.get(name) {            Some(s) => s,            None => 0.0,        };        sums.insert(name, prior_sum + value);    }    #[every(40ms)]    receive fn snapshot() {        snapshots_taken = snapshots_taken + 1;    }    receive fn mean(name: string) -> f64 {        let c = match counts.get(name) {            Some(c) => c,            None => 0,        };        if c == 0 {            return 0.0;        }        let s = match sums.get(name) {            Some(s) => s,            None => 0.0,        };        s / (c as f64)    }    receive fn count(name: string) -> i64 {        match counts.get(name) {            Some(c) => c,            None => 0,        }    }    receive fn snapshots() -> i64 {        snapshots_taken    }}fn percentile_label(p: f64) -> string {    match p {        v if v >= 0.99 => "p99",        v if v >= 0.95 => "p95",        v if v >= 0.5 => "p50",        _ => "low",    }}fn main() {    let collector = spawn Collector();    // Sends from inside a function closure are not yet implemented    // (captured pid loses its actor layout in the closure's MIR context);    // push samples from plain loops instead.    var i = 0;    while i < 100 {        collector.observe("api.latency", 10.0 + ((i % 50) as f64));        i = i + 1;    }    var j = 0;    while j < 50 {        collector.observe("db.latency", 3.0 + (j as f64));        j = j + 1;    }    sleep_ms(200);    match await collector.count("api.latency") {        Ok(n) => println(f"api.latency samples: {n}"),        Err(_) => println("ask failed: count"),    }    match await collector.mean("api.latency") {        Ok(m) => println(f"api.latency mean: {m}"),        Err(_) => println("ask failed: mean"),    }    match await collector.mean("db.latency") {        Ok(m) => println(f"db.latency mean: {m}"),        Err(_) => println("ask failed: mean"),    }    match await collector.snapshots() {        Ok(s) => {            if s >= 3 {                println("periodic snapshots: ok");            } else {                println(f"periodic snapshots: only {s}");            }        },        Err(_) => println("ask failed: snapshots"),    }    println(f"label: {percentile_label(0.97)}");}