2022-04-04 16:58:34 +02:00
|
|
|
use std::time::Instant;
|
|
|
|
|
|
|
|
use axum::{extract::MatchedPath, http::Request, middleware::Next, response::IntoResponse};
|
|
|
|
use metrics_exporter_prometheus::{Matcher, PrometheusBuilder, PrometheusHandle};
|
|
|
|
|
2022-04-28 10:56:30 +02:00
|
|
|
pub fn setup_metrics_recorder() -> PrometheusHandle {
|
2022-04-04 16:58:34 +02:00
|
|
|
const EXPONENTIAL_SECONDS: &[f64] = &[
|
|
|
|
0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0,
|
|
|
|
];
|
|
|
|
|
|
|
|
PrometheusBuilder::new()
|
|
|
|
.set_buckets_for_metric(
|
|
|
|
Matcher::Full("http_requests_duration_seconds".to_string()),
|
|
|
|
EXPONENTIAL_SECONDS,
|
|
|
|
)
|
|
|
|
.unwrap()
|
|
|
|
.install_recorder()
|
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Taken from the examples section
|
2022-04-28 10:56:30 +02:00
|
|
|
pub async fn track_metrics<B>(req: Request<B>, next: Next<B>) -> impl IntoResponse {
|
2022-04-04 16:58:34 +02:00
|
|
|
let start = Instant::now();
|
|
|
|
let path = if let Some(matched_path) = req.extensions().get::<MatchedPath>() {
|
|
|
|
matched_path.as_str().to_owned()
|
|
|
|
} else {
|
|
|
|
req.uri().path().to_owned()
|
|
|
|
};
|
|
|
|
let method = req.method().clone();
|
|
|
|
|
|
|
|
let response = next.run(req).await;
|
|
|
|
|
|
|
|
let latency = start.elapsed().as_secs_f64();
|
|
|
|
let status = response.status().as_u16().to_string();
|
|
|
|
|
|
|
|
let labels = [
|
|
|
|
("method", method.to_string()),
|
|
|
|
("path", path),
|
|
|
|
("status", status),
|
|
|
|
];
|
|
|
|
|
|
|
|
metrics::increment_counter!("http_requests_total", &labels);
|
|
|
|
metrics::histogram!("http_requests_duration_seconds", latency, &labels);
|
|
|
|
|
|
|
|
response
|
|
|
|
}
|