Skip to main content

observer/
observer.rs

1use std::sync::Arc;
2
3use mace::observe::{
4    CounterMetric, HistogramMetric, InMemoryObserver, ObserveEvent, ObserveSnapshot,
5};
6use mace::{BucketOptions, Mace, OpCode, Options};
7
8fn main() -> Result<(), OpCode> {
9    let path = std::env::temp_dir().join(format!("mace_observer_{}", std::process::id()));
10    let _ = std::fs::remove_dir_all(&path);
11
12    let observer = Arc::new(InMemoryObserver::new(256));
13    let mut opt = Options::new(&path);
14    opt.observer = observer.clone();
15
16    let db = Mace::new(opt.validate()?)?;
17    let bucket = db.new_bucket("observe", BucketOptions::default())?;
18
19    let tx = bucket.begin()?;
20    tx.put("k1", "v1")?;
21
22    let r = tx.put("k1", "v2");
23    assert_eq!(r.err(), Some(OpCode::AbortTx));
24    drop(tx);
25
26    let tx = bucket.begin()?;
27    tx.put("k2", "v2")?;
28    tx.commit()?;
29
30    let snapshot = observer.snapshot();
31    print_snapshot(&snapshot);
32    Ok(())
33}
34
35fn print_snapshot(snapshot: &ObserveSnapshot) {
36    println!("== non-zero counters ==");
37    for (metric, value) in &snapshot.counters {
38        if *value > 0 {
39            println!("{metric:?}: {value}");
40        }
41    }
42
43    println!("\n== non-empty histograms ==");
44    for (metric, sample) in &snapshot.histograms {
45        if sample.count > 0 {
46            let avg = sample.sum as f64 / sample.count as f64;
47            println!(
48                "{metric:?}: count={}, sum={}, max={}, avg={avg:.2}",
49                sample.count, sample.sum, sample.max
50            );
51        }
52    }
53
54    println!("\n== events ==");
55    for event in &snapshot.events {
56        print_event(event);
57    }
58
59    assert_counter_at_least(snapshot, CounterMetric::TxnBegin, 2);
60    assert_counter_at_least(snapshot, CounterMetric::TxnConflictAbort, 1);
61    assert_counter_at_least(snapshot, CounterMetric::TxnRollback, 1);
62    assert_counter_at_least(snapshot, CounterMetric::TxnCommit, 1);
63    assert_hist_not_empty(snapshot, HistogramMetric::WalAppendBytes);
64}
65
66fn print_event(event: &ObserveEvent) {
67    println!(
68        "{:?}: bucket_id={}, txid={}, file_id={}, value={}",
69        event.kind, event.bucket_id, event.txid, event.file_id, event.value
70    );
71}
72
73fn assert_counter_at_least(snapshot: &ObserveSnapshot, metric: CounterMetric, min_value: u64) {
74    let value = snapshot
75        .counters
76        .iter()
77        .find(|(m, _)| *m == metric)
78        .map(|(_, v)| *v)
79        .unwrap_or(0);
80    assert!(
81        value >= min_value,
82        "counter {metric:?} expected >= {min_value}, got {value}"
83    );
84}
85
86fn assert_hist_not_empty(snapshot: &ObserveSnapshot, metric: HistogramMetric) {
87    let count = snapshot
88        .histograms
89        .iter()
90        .find(|(m, _)| *m == metric)
91        .map(|(_, s)| s.count)
92        .unwrap_or(0);
93    assert!(
94        count > 0,
95        "histogram {metric:?} should have at least one sample"
96    );
97}