use std::time::Duration;
use textfile_metrics::MetricsWriter;
use tokio::time::sleep;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::DEBUG)
.init();
let metrics = MetricsWriter::new()?;
println!(
"Created metrics writer at: {}",
metrics.output_path().display()
);
println!("\n=== Example 1: Simple Counter ===");
let empty: Vec<(&str, &str)> = vec![];
metrics.counter("requests_total", empty.clone(), 1.0)?;
metrics.counter("requests_total", empty.clone(), 1.0)?;
metrics.counter("requests_total", empty.clone(), 1.0)?;
println!("Incremented requests_total by 3");
println!("\n=== Example 2: Simple Gauge ===");
metrics.gauge("temperature_celsius", empty.clone(), 23.5)?;
println!("Set temperature_celsius to 23.5");
println!("\n=== Example 3: Metrics with Labels ===");
let get_labels = vec![
("method".to_string(), "GET".to_string()),
("status".to_string(), "200".to_string()),
];
let post_labels = vec![
("method".to_string(), "POST".to_string()),
("status".to_string(), "201".to_string()),
];
metrics.counter("http_requests_total", get_labels.clone(), 100.0)?;
metrics.counter("http_requests_total", post_labels.clone(), 50.0)?;
println!("Created http_requests_total with method and status labels");
println!("\n=== Example 4: Multiple Gauges with Location Labels ===");
for (location, temp) in &[("office", 21.5), ("warehouse", 18.2), ("server_room", 19.8)] {
let labels = vec![("location".to_string(), location.to_string())];
metrics.gauge("temperature_celsius", labels, *temp)?;
}
println!("Created temperature_celsius gauges for 3 locations");
println!("\n=== Example 5: Convenience Methods ===");
metrics.inc("requests_received", empty.clone())?;
metrics.inc("requests_received", empty.clone())?;
println!("Used inc() to increment requests_received twice");
metrics.set("active_connections", empty.clone(), 42.0)?;
println!("Used set() to set active_connections to 42");
println!("\n=== Example 6: Time-series Updates ===");
for i in 1..=5 {
let value = 20.0 + (i as f64 * 0.5);
metrics.gauge("cpu_temperature_celsius", empty.clone(), value)?;
println!(" Update {}: cpu_temperature = {:.1}°C", i, value);
sleep(Duration::from_millis(100)).await;
}
println!("\n=== Example 7: Error Handling ===");
match metrics.gauge("invalid", empty.clone(), f64::NAN) {
Ok(_) => println!("NaN was accepted (unexpected)"),
Err(e) => println!("NaN correctly rejected: {}", e),
}
match metrics.counter("9invalid_name", empty.clone(), 1.0) {
Ok(_) => println!("Invalid name was accepted (unexpected)"),
Err(e) => println!("Invalid name correctly rejected: {}", e),
}
println!("\n=== Metrics State ===");
println!("Total distinct metrics: {}", metrics.len());
println!("\n=== Flushing Metrics ===");
metrics.flush().await?;
println!(
"Metrics flushed to {}/metrics.prom",
metrics.output_path().display()
);
let output_path = metrics.output_path().join("metrics.prom");
if output_path.exists() {
let content = std::fs::read_to_string(&output_path)?;
println!("\n=== Generated metrics.prom ===");
println!("{}", content);
}
Ok(())
}