use std::sync::OnceLock;
use metrics_exporter_prometheus::{PrometheusBuilder, PrometheusHandle};
use crate::infrastructure::http::axum_adapter::PjsError;
static RECORDER: OnceLock<PrometheusHandle> = OnceLock::new();
pub fn install_global_recorder() -> Result<PrometheusHandle, PjsError> {
RECORDER
.get_or_try_init(|| {
PrometheusBuilder::new().install_recorder().map_err(|e| {
PjsError::HttpError(format!("failed to install Prometheus recorder: {e}"))
})
})
.cloned()
}
pub async fn metrics_handler() -> impl axum::response::IntoResponse {
match install_global_recorder() {
Ok(handle) => {
let body = handle.render();
axum::response::Response::builder()
.status(axum::http::StatusCode::OK)
.header(
axum::http::header::CONTENT_TYPE,
"text/plain; version=0.0.4; charset=utf-8",
)
.body(axum::body::Body::from(body))
.unwrap_or_else(|_| {
axum::response::Response::builder()
.status(axum::http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::empty())
.expect("infallible empty response")
})
}
Err(e) => axum::response::Response::builder()
.status(axum::http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::from(e.to_string()))
.expect("infallible error response"),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn install_is_idempotent() {
let h1 = install_global_recorder().expect("first install");
let h2 = install_global_recorder().expect("second install");
assert_eq!(h1.render(), h2.render());
}
}