use prometheus::{IntCounter, Opts, Registry};
use prometheus_hyper::{RegistryFn, Server};
use std::{
error::Error,
net::SocketAddr,
sync::{
Arc,
atomic::{AtomicBool, Ordering},
},
time::Duration,
};
use tracing::{debug, info};
pub struct Metrics {
pub seconds_total: IntCounter,
}
impl Metrics {
pub fn new() -> Result<(Self, RegistryFn), Box<dyn Error>> {
let seconds_total = IntCounter::with_opts(Opts::new(
"seconds_total",
"count the runtime of this service in seconds",
))?;
let seconds_total_clone = seconds_total.clone();
let f = |registry: &Registry| {
registry.register(Box::new(seconds_total_clone))?;
Ok(())
};
Ok((Self { seconds_total }, Box::new(f)))
}
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
tracing_subscriber::fmt().with_max_level(tracing::Level::TRACE).init();
info!("Starting clock...");
let running = Arc::new(AtomicBool::new(true));
let registry = Arc::new(Registry::new());
let (metrics, f) = Metrics::new().expect("failed prometheus");
f(®istry).expect("problem registering");
tokio::spawn(Server::run(
Arc::clone(®istry),
SocketAddr::from(([0; 4], 8080)),
shutdown_signal(Arc::clone(&running)),
));
let mut sec_int = tokio::time::interval(Duration::from_secs(1));
while running.load(Ordering::Relaxed) {
sec_int.tick().await;
metrics.seconds_total.inc();
debug!("tick");
sec_int.tick().await;
metrics.seconds_total.inc();
debug!("tock");
}
info!("stopped clock");
}
async fn shutdown_signal(running: Arc<AtomicBool>) {
tokio::signal::ctrl_c()
.await
.expect("Failed to install CTRL+C signal handler");
running.store(false, Ordering::Relaxed);
}