< 返回版块

SchafferJ 发表于 2023-09-27 14:11

Tags:tokio

在使用tokio、axum、tracing的时候,想要打印入参的body参数,发现body的读取方法是异步的,这种情况下改怎么做呢

#[tokio::main]
async fn main() {
    tracing_subscriber::registry()
        .with(
            tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| {
                // axum logs rejections from built-in extractors with the `axum::rejection`
                // target, at `TRACE` level. `axum::rejection=trace` enables showing those events
                "example_tracing_aka_logging=debug,tower_http=debug,axum::rejection=trace".into()
            }),
        )
        .with(tracing_subscriber::fmt::layer())
        .init();

    // build our application with a route
    let app = Router::new()
        .route("/", get(handler))
        // `TraceLayer` is provided by tower-http so you have to add that as a dependency.
        // It provides good defaults but is also very customizable.
        //
        // See https://docs.rs/tower-http/0.1.1/tower_http/trace/index.html for more details.
        //
        // If you want to customize the behavior using closures here is how.
        .layer(
            TraceLayer::new_for_http()
                .make_span_with(|request: &Request<_>| {
                    // Log the matched route's path (with placeholders not filled in).
                    // Use request.uri() or OriginalUri if you want the real path.
                    let matched_path = request
                        .extensions()
                        .get::<MatchedPath>()
                        .map(MatchedPath::as_str);

                    info_span!(
                        "http_request",
                        method = ?request.method(),
                        matched_path,
                        some_other_field = tracing::field::Empty,
                    )
                })
                .on_request(|_request: &Request<_>, _span: &Span| {
                    // You can use `_span.record("some_other_field", value)` in one of these
                    // closures to attach a value to the initially empty field in the info_span
                    // created above.
                })
                .on_response(|_response: &Response, _latency: Duration, _span: &Span| {
                    // ...
                })
                .on_body_chunk(|_chunk: &Bytes, _latency: Duration, _span: &Span| {
                    // ...
                })
                .on_eos(
                    |_trailers: Option<&HeaderMap>, _stream_duration: Duration, _span: &Span| {
                        // ...
                    },
                )
                .on_failure(
                    |_error: ServerErrorsFailureClass, _latency: Duration, _span: &Span| {
                        // ...
                    },
                ),
        );

    // run it
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    tracing::debug!("listening on {}", addr);
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}

以上是axum的examples中的代码,在on_request中读取body: hyper::body::to_bytes(_request.body())

评论区

写评论
我心飞翔 2023-09-28 10:27

使用 crate futures 的 futures::executor::block_on

作者 SchafferJ 2023-09-27 15:59

这个我试试,可是这样的话http日志就散落在两个地方,一部分在TraceLayer另一部分在自定义的middleware里

--
👇
ruby: TraceLayer的方法都是同步的,你应该用axum的middleware写个请求拦截器/中间件拦截请求,会有个异步的回调让你打印每个request的body

Nayaka 2023-09-27 15:47

为何不用axum的middleware呢

https://github.com/tokio-rs/axum/blob/main/examples/consume-body-in-extractor-or-middleware/src/main.rs

https://github.com/tokio-rs/axum/blob/main/examples/print-request-response/src/main.rs

作者 SchafferJ 2023-09-27 15:11

可以写一些代码例子不,我也搜到过一些类似的文章,不过都不太好用看起来,比如要自己实例化异步运行时

--
👇
JasonkayZK: 试试 block_on

ruby 2023-09-27 14:43

TraceLayer的方法都是同步的,你应该用axum的middleware写个请求拦截器/中间件拦截请求,会有个异步的回调让你打印每个request的body

JasonkayZK 2023-09-27 14:29

试试 block_on

1 共 6 条评论, 1 页