Skip to main content

soma_http_server/middleware/
tracing.rs

1//! Generic HTTP request tracing.
2//!
3//! A thin, named constructor over `tower_http`'s default HTTP trace layer so
4//! callers don't have to spell out the classifier type. Products that want
5//! custom spans (e.g. including the request ID) can still reach for
6//! `tower_http::trace::TraceLayer` directly and layer it alongside
7//! [`crate::middleware::request_id`].
8
9use tower_http::classify::{ServerErrorsAsFailures, SharedClassifier};
10use tower_http::trace::TraceLayer;
11
12/// Concrete type returned by [`trace_layer`] — spelled out once here so
13/// callers don't need to name `tower_http`'s classifier generics themselves.
14pub type HttpTraceLayer = TraceLayer<SharedClassifier<ServerErrorsAsFailures>>;
15
16/// Build a `tower_http` request tracing layer with the library's default
17/// HTTP classification (5xx responses and transport errors count as
18/// failures; everything else is a success span).
19pub fn trace_layer() -> HttpTraceLayer {
20    TraceLayer::new_for_http()
21}
22
23#[cfg(test)]
24mod tests {
25    use super::*;
26    use axum::{body::Body, http::Request, routing::get, Router};
27    use tower::ServiceExt;
28
29    #[tokio::test]
30    async fn trace_layer_passes_requests_through_unchanged() {
31        let app = Router::new()
32            .route("/", get(|| async { "ok" }))
33            .layer(trace_layer());
34
35        let request = Request::builder().uri("/").body(Body::empty()).unwrap();
36        let response = app.oneshot(request).await.unwrap();
37        assert_eq!(response.status(), axum::http::StatusCode::OK);
38    }
39}