如何在单独的函数中配置 tower_http TraceLayer?
How to configure tower_http TraceLayer in a separate function?
我正在实施 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
...
为了稍微组织一下代码,我将跟踪层配置移到了一个单独的函数中。诀窍是为此函数提供编译 return 类型。
第一种方法是按原样移动代码并让 IDE 生成 return 类型:
TraceLayer<SharedClassifier<ServerErrorsAsFailures>, fn(&Request<Body>) -> Span, fn(&Request<Body>, &Span), fn(&Response<BoxBody>, Duration, &Span), DefaultOnBodyChunk, DefaultOnEos, fn(ServerErrorsFailureClass, Duration, &Span)>
完全不可读,但最糟糕的是它无法编译:“需要 fn 指针,找到闭包”
在第二种方法中,我将 fn
更改为 impl Fn
,这意味着闭包类型。同样,我得到一个错误,我的闭包不是 Clone
.
第三,我尝试将闭包提取到单独的函数中。但后来我得到“预期的 fn 指针,找到 fn 项”。
我该怎么做 1) 使其编译并 2) 使其更具可读性?
这个问题比较笼统,但 Whosebug 提醒我要具体,所以我举一个具体的例子来说明我目前的痛苦。
根据经验,由于所有泛型,像这样分解代码非常困难。相反,我会推荐接受和 return axum::Routers
的函数。这样你就绕过了所有的泛型:
fn add_middleware(router: Router) -> Router {
router.layer(
TraceLayer::new_for_http().make_span_with(...)
)
}
我正在实施 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
...
为了稍微组织一下代码,我将跟踪层配置移到了一个单独的函数中。诀窍是为此函数提供编译 return 类型。
第一种方法是按原样移动代码并让 IDE 生成 return 类型:
TraceLayer<SharedClassifier<ServerErrorsAsFailures>, fn(&Request<Body>) -> Span, fn(&Request<Body>, &Span), fn(&Response<BoxBody>, Duration, &Span), DefaultOnBodyChunk, DefaultOnEos, fn(ServerErrorsFailureClass, Duration, &Span)>
完全不可读,但最糟糕的是它无法编译:“需要 fn 指针,找到闭包”
在第二种方法中,我将 fn
更改为 impl Fn
,这意味着闭包类型。同样,我得到一个错误,我的闭包不是 Clone
.
第三,我尝试将闭包提取到单独的函数中。但后来我得到“预期的 fn 指针,找到 fn 项”。
我该怎么做 1) 使其编译并 2) 使其更具可读性?
这个问题比较笼统,但 Whosebug 提醒我要具体,所以我举一个具体的例子来说明我目前的痛苦。
根据经验,由于所有泛型,像这样分解代码非常困难。相反,我会推荐接受和 return axum::Routers
的函数。这样你就绕过了所有的泛型:
fn add_middleware(router: Router) -> Router {
router.layer(
TraceLayer::new_for_http().make_span_with(...)
)
}