diff options
author | Ellie Huxtable <ellie@elliehuxtable.com> | 2024-04-18 16:41:28 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-18 16:41:28 +0100 |
commit | 95cc472037fcb3207b510e67f1a44af4e2a2cae9 (patch) | |
tree | fc1d3e71d8e0bdb806370e4144fd6f373bcc9c5e /crates/atuin-server/src/metrics.rs | |
parent | 176eae02f7f855ef40a4461caca61d530486113f (diff) |
chore: move crates into crates/ dir (#1958)
I'd like to tidy up the root a little, and it's nice to have all the
rust crates in one place
Diffstat (limited to 'crates/atuin-server/src/metrics.rs')
-rw-r--r-- | crates/atuin-server/src/metrics.rs | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/crates/atuin-server/src/metrics.rs b/crates/atuin-server/src/metrics.rs new file mode 100644 index 00000000..0a7ac6bd --- /dev/null +++ b/crates/atuin-server/src/metrics.rs @@ -0,0 +1,56 @@ +use std::time::Instant; + +use axum::{ + extract::{MatchedPath, Request}, + middleware::Next, + response::IntoResponse, +}; +use metrics_exporter_prometheus::{Matcher, PrometheusBuilder, PrometheusHandle}; + +pub fn setup_metrics_recorder() -> PrometheusHandle { + 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() +} + +/// Middleware to record some common HTTP metrics +/// Generic over B to allow for arbitrary body types (eg Vec<u8>, Streams, a deserialized thing, etc) +/// Someday tower-http might provide a metrics middleware: https://github.com/tower-rs/tower-http/issues/57 +pub async fn track_metrics(req: Request, next: Next) -> impl IntoResponse { + 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(); + + // Run the rest of the request handling first, so we can measure it and get response + // codes. + 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 +} |