#[cfg(feature = "metrics")]
mod demo {
use std::sync::Arc;
use std::time::Duration;
use amalgam::{Cache, MetricsPlugin};
use metrics_exporter_prometheus::PrometheusBuilder;
const LISTEN_ADDR: ([u8; 4], u16) = ([0, 0, 0, 0], 9000);
pub async fn run() -> Result<(), Box<dyn std::error::Error>> {
PrometheusBuilder::new()
.with_http_listener(LISTEN_ADDR)
.install()?;
println!("metrics exposed at http://127.0.0.1:9000/metrics");
println!(
"Prometheus (docker compose) scrapes host.docker.internal:9000 — UI: http://localhost:9090"
);
println!();
let cache: Cache<String> = Cache::builder()
.plugin(Arc::new(MetricsPlugin::new()))
.build();
const ITERATIONS: u32 = 120;
println!("running a {ITERATIONS}-iteration workload (Ctrl-C to stop early) …");
for i in 0..ITERATIONS {
let key = format!("item-{}", i % 4);
let _ = cache
.get_or_set(key.clone(), move |ctx| async move {
Ok(ctx.value(format!("value-for-{key}")))
})
.await?;
if i % 5 == 0 {
cache
.set(format!("explicit-{i}"), "set-directly".to_owned())
.await;
}
if i % 8 == 0 {
cache.remove(format!("item-{}", i % 4)).await;
}
if i % 20 == 0 {
println!(" iteration {i}: counters advancing — scrape /metrics to watch them");
}
tokio::time::sleep(Duration::from_millis(250)).await;
}
println!();
println!("workload complete. The recorder stays installed; the process now");
println!("idles so a final scrape can read the totals. Press Ctrl-C to exit.");
for _ in 0..60 {
tokio::time::sleep(Duration::from_secs(1)).await;
}
Ok(())
}
}
#[tokio::main]
async fn main() {
#[cfg(feature = "metrics")]
if let Err(err) = demo::run().await {
eprintln!("error: {err}");
}
#[cfg(not(feature = "metrics"))]
{
eprintln!("This example requires the `metrics` feature:");
eprintln!(" cargo run --example prometheus --features metrics");
}
}