Thanks to visit codestin.com
Credit goes to github.com

Skip to content

TraceLayer some requests don't have span attached #655

@juchiast

Description

@juchiast
  • I have looked for existing issues (including closed) about this

Bug Report

Version

0.6.8

Platform

Linux

Description

I'm using tower-http TraceLayer to log axum requests, however, sometime the log doesn't have any span attached to it, for example:

server-1  | 2026-03-07T06:47:27.963867Z DEBUG tower_http::trace::on_request: started processing request
server-1  | 2026-03-07T06:47:27.963959Z DEBUG tower_http::trace::on_response: finished processing request latency=0 ms status=200
server-1  | 2026-03-07T06:47:28.375252Z DEBUG tower_http::trace::on_request: started processing request
server-1  | 2026-03-07T06:47:51.871866Z DEBUG request{method=OPTIONS uri=/v1/game/me/currency/data/balance version=HTTP/1.1}: tower_http::trace::on_request: started processing request
server-1  | 2026-03-07T06:47:51.872013Z DEBUG request{method=OPTIONS uri=/v1/game/me/currency/data/balance version=HTTP/1.1}: tower_http::trace::on_response: finished processing request latency=0 ms status=200
server-1  | 2026-03-07T06:47:53.819640Z DEBUG request{method=GET uri=/v1/game/me/currency/data/balance version=HTTP/1.1}: tower_http::trace::on_request: started processing request
server-1  | 2026-03-07T06:47:54.477762Z DEBUG request{method=OPTIONS uri=/v1/game/me/casual/energy_balance version=HTTP/1.1}: tower_http::trace::on_request: started processing request
server-1  | 2026-03-07T06:47:54.477868Z DEBUG request{method=OPTIONS uri=/v1/game/me/casual/energy_balance version=HTTP/1.1}: tower_http::trace::on_response: finished processing request latency=0 ms status=200
server-1  | 2026-03-07T06:47:55.132684Z DEBUG request{method=GET uri=/v1/game/me/casual/energy_balance version=HTTP/1.1}: tower_http::trace::on_request: started processing request
server-1  | 2026-03-07T06:48:17.030890Z DEBUG tower_http::trace::on_request: started processing request
server-1  | 2026-03-07T06:48:17.030990Z DEBUG tower_http::trace::on_response: finished processing request latency=0 ms status=200
server-1  | 2026-03-07T06:48:17.283262Z DEBUG request{method=POST uri=/v1/game/me/run/start version=HTTP/1.1}: tower_http::trace::on_request: started processing request
server-1  | 2026-03-07T06:54:21.256843Z DEBUG tower_http::trace::on_request: started processing request
server-1  | 2026-03-07T06:54:22.811286Z DEBUG request{method=GET uri=/ version=HTTP/1.1}: tower_http::trace::on_request: started processing request

Lines like this:

server-1  | 2026-03-07T06:48:17.030890Z DEBUG tower_http::trace::on_request: started processing request
server-1  | 2026-03-07T06:48:17.030990Z DEBUG tower_http::trace::on_response: finished processing request latency=0 ms status=200

This is how I configure logging:

pub mod log {
    use std::time::Duration;

    use axum::http::StatusCode;
    use tower_http::trace::{DefaultOnResponse, OnResponse, TraceLayer};
    use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer};

    #[derive(Clone)]
    pub struct OnResponseImpl<T> {
        inner: T,
    }

    impl<B, T> OnResponse<B> for OnResponseImpl<T>
    where
        T: OnResponse<B>,
    {
        fn on_response(
            self,
            response: &axum::http::Response<B>,
            latency: Duration,
            span: &tracing::Span,
        ) {
            if response.status() != StatusCode::NOT_FOUND {
                self.inner.on_response(response, latency, span)
            }
        }
    }

    pub fn init_tracing() {
        tracing_subscriber::registry()
            .with(tracing_subscriber::fmt::layer().with_filter(
                EnvFilter::from_default_env().add_directive("tower_http=debug".parse().unwrap()),
            ))
            .init();
    }

    pub fn layer() -> TraceLayer<
        tower_http::classify::SharedClassifier<tower_http::classify::ServerErrorsAsFailures>,
        tower_http::trace::DefaultMakeSpan,
        tower_http::trace::DefaultOnRequest,
        OnResponseImpl<DefaultOnResponse>,
    > {
        TraceLayer::new_for_http().on_response(OnResponseImpl {
            inner: DefaultOnResponse::new(),
        })
    }
}

I have a custom OnResponseImpl to filter out the 404 responses.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions