pub fn run(url: Option<&str>, interval: Option<u64>) -> anyhow::Result<()> {
let interval_secs = interval.unwrap_or(2);
let metrics_url = url
.map(|u| u.to_string())
.or_else(|| std::env::var("METRICS_URL").ok())
.unwrap_or_else(|| "http://localhost:3000/metrics".to_string());
println!("rok metrics — live dashboard");
println!("{}", "─".repeat(60));
println!(" Source: {metrics_url}");
println!(" Refresh: every {interval_secs}s");
println!(" Press Ctrl+C to exit.");
println!("{}", "─".repeat(60));
let mut iteration = 0u64;
loop {
iteration += 1;
println!();
println!(" [tick #{iteration}] {}", chrono::Utc::now().format("%H:%M:%S"));
match fetch_metrics(&metrics_url) {
Ok(body) => {
let lines: Vec<&str> = body.lines()
.filter(|l| !l.starts_with('#') && !l.trim().is_empty())
.take(20)
.collect();
for line in lines {
println!(" {line}");
}
if body.lines().filter(|l| !l.starts_with('#') && !l.trim().is_empty()).count() > 20 {
println!(" … (see {metrics_url} for full output)");
}
}
Err(e) => {
println!(" ! could not reach {metrics_url}: {e}");
println!(" Ensure your app is running with a /metrics endpoint.");
}
}
std::thread::sleep(std::time::Duration::from_secs(interval_secs));
}
}
fn fetch_metrics(url: &str) -> anyhow::Result<String> {
let mut resp = ureq::get(url)
.header("Accept", "text/plain; version=0.0.4")
.call()?;
Ok(resp.body_mut().read_to_string()?)
}