use std::time::Instant;
use metrics::{counter, describe_counter, describe_gauge, describe_histogram, gauge, histogram};
use metrics_exporter_prometheus::{PrometheusBuilder, PrometheusHandle};
pub(crate) const RESTART_TOTAL: &str = "lightshuttle_restart_total";
pub(crate) const EVENT_DURATION: &str = "lightshuttle_lifecycle_event_duration_seconds";
const RESOURCES: &str = "lightshuttle_resources";
const UPTIME: &str = "lightshuttle_uptime_seconds";
pub struct Metrics {
handle: PrometheusHandle,
started: Instant,
}
impl Metrics {
#[must_use]
pub fn install() -> Self {
let handle = PrometheusBuilder::new()
.install_recorder()
.expect("failed to install the Prometheus recorder");
describe_metrics();
Self {
handle,
started: Instant::now(),
}
}
#[must_use]
pub fn for_test() -> Self {
let recorder = PrometheusBuilder::new().build_recorder();
let handle = recorder.handle();
Self {
handle,
started: Instant::now(),
}
}
#[must_use]
pub fn render(&self, status_counts: &[(&str, u64)]) -> String {
for (status, count) in status_counts {
#[allow(clippy::cast_precision_loss)]
gauge!(RESOURCES, "status" => (*status).to_owned()).set(*count as f64);
}
#[allow(clippy::cast_precision_loss)]
gauge!(UPTIME).set(self.started.elapsed().as_secs_f64());
self.handle.render()
}
}
pub(crate) fn record_restart() {
counter!(RESTART_TOTAL).increment(1);
}
pub fn observe_event_duration(seconds: f64) {
histogram!(EVENT_DURATION).record(seconds);
}
fn describe_metrics() {
describe_counter!(RESTART_TOTAL, "Total number of accepted restart requests");
describe_histogram!(
EVENT_DURATION,
"Seconds a resource takes to go from started to healthy"
);
describe_gauge!(RESOURCES, "Number of managed resources, labelled by status");
describe_gauge!(UPTIME, "Orchestrator uptime in seconds");
}