use std::time::Instant;
use axum::{
Router,
body::Body,
extract::{MatchedPath, State},
http::Request,
middleware::Next,
response::IntoResponse,
routing::get,
};
use crate::observability::{HttpMetricLabels, MetricsRegistry};
pub async fn record_metrics_middleware(
State(registry): State<MetricsRegistry>,
request: Request<Body>,
next: Next,
) -> impl IntoResponse {
let method = request.method().to_string();
let route = request
.extensions()
.get::<MatchedPath>()
.map(|path| path.as_str().to_string())
.unwrap_or_else(|| "unknown".to_string());
let started = Instant::now();
let response = next.run(request).await;
let status = response.status().as_u16();
registry.record_http_request(
HttpMetricLabels::new(method, route, status),
started.elapsed(),
);
response
}
pub fn metrics_router(registry: MetricsRegistry) -> Router {
Router::new().route(
"/metrics",
get(move || {
let registry = registry.clone();
async move { registry.render_prometheus() }
}),
)
}