簡體   English   中英

如何記錄 spring-webflux WebClient 請求 + 響應詳細信息(主體、標題、elasped_time)?

[英]How to log spring-webflux WebClient request + response details (bodies, headers, elasped_time)?

基本上,我想在一個包含帶有 Spring WebClient body/headers 的日志中記錄請求/響應信息。

隨着春天RestTemplate我們可以用做ClientHttpRequestInterceptor 我找到了有關 Spring WebClient ExchangeFilterFunction ,但還沒有設法以干凈的方式做類似的事情。 我們可以使用這個過濾器並記錄請求,然后記錄響應,但我需要在同一個日志跟蹤中。

此外,我還沒有設法使用ExchangeFilterFunction.ofResponseProcessor方法獲得響應正文。

我期待這樣的日志(當前實現與 ClientHttpRequestInterceptor 一起使用),其中包含我需要的所有信息:

{
    "@timestamp": "2019-05-14T07:11:29.089+00:00",
    "@version": "1",
    "message": "GET https://awebservice.com/api",
    "logger_name": "com.sample.config.resttemplate.LoggingRequestInterceptor",
    "thread_name": "http-nio-8080-exec-5",
    "level": "TRACE",
    "level_value": 5000,
    "traceId": "e65634ee6a7c92a7",
    "spanId": "7a4d2282dbaf7cd5",
    "spanExportable": "false",
    "X-Span-Export": "false",
    "X-B3-SpanId": "7a4d2282dbaf7cd5",
    "X-B3-ParentSpanId": "e65634ee6a7c92a7",
    "X-B3-TraceId": "e65634ee6a7c92a7",
    "parentId": "e65634ee6a7c92a7",
    "method": "GET",
    "uri": "https://awebservice.com/api",
    "body": "[Empty]",
    "elapsed_time": 959,
    "status_code": 200,
    "status_text": "OK",
    "content_type": "text/html",
    "response_body": "{"message": "Hello World!"}"
}

有沒有人設法用 Spring WebClient 做這樣的事情? 或者如何繼續跟蹤 Spring WebClient 的請求/響應問題?

您可以使用 filter(),如下所示:

this.webClient = WebClient.builder().baseUrl("your_url")
            .filter(logRequest())
            .filter(logResponse())
            .build();

private ExchangeFilterFunction logRequest() {
    return (clientRequest, next) -> {
        log.info("Request: {} {}", clientRequest.method(), clientRequest.url());
        clientRequest.headers()
                .forEach((name, values) -> values.forEach(value -> log.info("{}={}", name, value)));
        return next.exchange(clientRequest);
    };
}

private ExchangeFilterFunction logResponse() {
    return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
        log.info("Response: {}", clientResponse.headers().asHttpHeaders().get("property-header"));
        return Mono.just(clientResponse);
    });
}

我認為您不能調用.bodyToMono兩次(一次在過濾器中,然后在您使用客戶端的地方再次調用),因此您可能無法將其記錄在過濾器中。 至於其他細節……

WebClient 配置:

@Configuration
class MyClientConfig {

    @Bean
    fun myWebClient(): WebClient {
        return WebClient
            .builder()
            .baseUrl(myUrl)
            .filter(MyFilter())
            .build()
    }
}

過濾器:

class MyFilter : ExchangeFilterFunction {

    override fun filter(request: ClientRequest, next: ExchangeFunction): Mono<ClientResponse> {
        return next.exchange(request).flatMap { response ->

            // log whenever you want here...
            println("request: ${request.url()}, response: ${response.statusCode()}")

            Mono.just(response)
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM