crates/mimir-ingest/examples/stats.rs
//! Per-commit event counts of a lake written by `consume`:
//! `stats <state-dir> <repo>` → one line per seq: node +/−, edge +/− (and
//! span +/− once the lake has a span table).
use std::collections::BTreeMap;
use anyhow::Result;
use mimir_ingest::{EventLog, Kind, Specs};
use skade::arrow_array::{Array, Int64Array, StringArray};
use skade::arrow_schema::DataType;
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
let a: Vec<String> = std::env::args().skip(1).collect();
anyhow::ensure!(a.len() == 2, "usage: stats <state-dir> <repo>");
let wh = skade::open(std::path::Path::new(&a[0]).join("lake")).await?;
let log = EventLog::open(wh, Specs::mimir()?).await?;
let kinds = Kind::ALL;
let mut per: BTreeMap<i64, Vec<(u64, u64)>> = BTreeMap::new();
for (ki, kind) in kinds.iter().enumerate() {
for b in log.events(*kind).await? {
let repo = skade::arrow_cast::cast(b.column_by_name("repo").unwrap(), &DataType::Utf8)?;
let repo = repo.as_any().downcast_ref::<StringArray>().unwrap();
let op = skade::arrow_cast::cast(b.column_by_name("op").unwrap(), &DataType::Utf8)?;
let op = op.as_any().downcast_ref::<StringArray>().unwrap();
let seq = b.column_by_name("seq").unwrap().as_any().downcast_ref::<Int64Array>().unwrap().clone();
for i in 0..b.num_rows() {
if repo.value(i) != a[1] {
continue;
}
let e = per.entry(seq.value(i)).or_insert_with(|| vec![(0, 0); kinds.len()]);
if op.value(i) == "+" { e[ki].0 += 1 } else { e[ki].1 += 1 }
}
}
}
println!("seq {}", kinds.iter().map(|k| format!("{:>18}", format!("{k:?} +/-"))).collect::<String>());
for (seq, v) in per {
println!("{seq:>3} {}", v.iter().map(|(p, m)| format!("{:>18}", format!("+{p}/-{m}"))).collect::<String>());
}
Ok(())
}