如何在单独的函数中配置 tower_http TraceLayer?

iTo*_*llu 2 rust rust-tower

我正在实现 tokio/axum HTTP 服务器。在运行服务器的函数中,我配置路由、添加共享应用程序服务并添加跟踪层。

我的跟踪配置如下所示:

let tracing_layer = TraceLayer::new_for_http()
    .make_span_with(|_request: &Request<Body>| {
        let request_id = Uuid::new_v4().to_string();
        tracing::info_span!("http-request", %request_id)
    })
    .on_request(|request: &Request<Body>, _span: &Span| {
        tracing::info!("request: {} {}", request.method(), request.uri().path())
    })
    .on_response(
        |response: &Response<BoxBody>, latency: Duration, _span: &Span| {
            tracing::info!("response: {} {:?}", response.status(), latency)
        },
    )
    .on_failure(
        |error: ServerErrorsFailureClass, _latency: Duration, _span: &Span| {
            tracing::error!("error: {}", error)
        },
    );

let app = Router::new()
    // routes
    .layer(tracing_layer)
    // other layers
...
Run Code Online (Sandbox Code Playgroud)

为了稍微组织一下代码,我将跟踪层配置移动到一个单独的函数中。诀窍是为此函数提供一个编译返回类型。

第一种方法是按原样移动代码并让 IDE 生成返回类型:

TraceLayer<SharedClassifier<ServerErrorsAsFailures>, fn(&Request<Body>) -> Span, fn(&Request<Body>, &Span), fn(&Response<BoxBody>, Duration, &Span), DefaultOnBodyChunk, DefaultOnEos, fn(ServerErrorsFailureClass, Duration, &Span)>
Run Code Online (Sandbox Code Playgroud)

这是完全不可读的,但最糟糕的是它无法编译:“预期的 fn 指针,发现闭包”

在第二种方法中,我将其更改fnimpl Fn闭包类型。我再次收到一个错误,指出我的closures not Clone

第三,我尝试将闭包提取到单独的函数中。但后来我得到“预期的 fn 指针,找到的 fn 项”。

我能做什么 1)使其编译并 2)使其更具可读性?

Dav*_*sen 6

从经验来看,由于所有泛型,像这样分解代码非常困难。相反,我会推荐接受并返回的函数axum::Routers。这样你就可以绕过所有泛型:

fn add_middleware(router: Router) -> Router {
    router.layer(
        TraceLayer::new_for_http().make_span_with(...)
    )
}
Run Code Online (Sandbox Code Playgroud)

  • `路由器 = add_middleware(路由器);` (2认同)