Spring 5 WebClientを使用してリクエストを記録しようとしています。どうすればそれを達成できますか?
(Spring 5とSpring Boot 2を使用しています)
現時点では、コードは次のようになっています。
try {
return webClient.get().uri(url, urlParams).exchange().flatMap(response -> response.bodyToMono(Test.class))
.map(test -> xxx.set(test));
} catch (RestClientException e) {
log.error("Cannot get counter from opus", e);
throw e;
}
ExchangeFilterFunction を使用して簡単に実行できます
_WebClient.Builder
_を使用してlogRequest
を作成するときに、カスタムWebClient
フィルターを追加するだけです。
そのようなフィルターの例と、それをWebClient
に追加する方法を以下に示します。
_@Slf4j
@Component
public class MyClient {
private final WebClient webClient;
// Create WebClient instance using builder.
// If you use spring-boot 2.0, the builder will be autoconfigured for you
// with the "prototype" scope, meaning each injection point will receive
// a newly cloned instance of the builder.
public MyClient(WebClient.Builder webClientBuilder) {
webClient = webClientBuilder // you can also just use WebClient.builder()
.baseUrl("https://httpbin.org")
.filter(logRequest()) // here is the magic
.build();
}
// Just example of sending request
public void send(String path) {
ClientResponse clientResponse = webClient
.get().uri(uriBuilder -> uriBuilder.path(path)
.queryParam("param", "value")
.build())
.exchange()
.block();
log.info("Response: {}", clientResponse.toEntity(String.class).block());
}
// This method returns filter function which will log request data
private static ExchangeFilterFunction logRequest() {
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
log.info("Request: {} {}", clientRequest.method(), clientRequest.url());
clientRequest.headers().forEach((name, values) -> values.forEach(value -> log.info("{}={}", name, value)));
return Mono.just(clientRequest);
});
}
}
_
次に、myClient.send("get");
を呼び出すだけで、ログメッセージが表示されます。
出力例:
_Request: GET https://httpbin.org/get?param=value
header1=value1
header2=value2
_
必ずしも独自のロガーをロールする必要はありません。reactor.ipc.netty.channel.ChannelOperationsHandler
が自動的に行います。そのクラスのロギングシステムをDEBUGレベルでログするように設定するだけです。
2017-11-23 12:52:04.562 DEBUG 41449 --- [ctor-http-nio-5] r.i.n.channel.ChannelOperationsHandler : [id: 0x9183d6da, L:/127.0.0.1:57681 - R:localhost/127.0.0.1:8000] Writing object DefaultFullHttpRequest(decodeResult: success, version: HTTP/1.1, content: UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeHeapByteBuf(ridx: 0, widx: 0, cap: 0))
GET /api/v1/watch/namespaces/default/events HTTP/1.1
user-agent: ReactorNetty/0.7.1.RELEASE
Host: localhost:8000
accept-encoding: gzip
Accept: application/json
content-length: 0
バグを減らす1つの方法は、可能な限りコードを記述しないことです。
2018年11月:
spring-webflux:5.1.2.RELEASE
を使用すると、上記は機能しなくなります。代わりに次を使用してください。
logging.level.org.springframework.web.reactive.function.client.ExchangeFunctions=DEBUG
...
2018-11-06 20:58:58.181 DEBUG 20300 --- [ main] o.s.w.r.f.client.ExchangeFunctions : [2026fbff] HTTP GET http://localhost:8080/stocks/search?symbol=AAPL
2018-11-06 20:58:58.451 DEBUG 20300 --- [ctor-http-nio-4] o.s.w.r.f.client.ExchangeFunctions : [2026fbff] Response 400 BAD_REQUEST
ヘッダーまたはフォーム本文を記録するには、上記をTRACE
レベルに設定します。ただし、それだけでは不十分です。
ExchangeStrategies exchangeStrategies = ExchangeStrategies.withDefaults();
exchangeStrategies
.messageWriters().stream()
.filter(LoggingCodecSupport.class::isInstance)
.forEach(writer -> ((LoggingCodecSupport)writer).setEnableLoggingRequestDetails(true));
client = WebClient.builder()
.exchangeStrategies(exchangeStrategies)
2019年3月:
リクエストとレスポンスの本文を記録する方法を尋ねたコメントの質問に答えて、Springがそのようなロガーを持っているが、WebClient
がNetty上に構築されているのかわかりません。したがって、パッケージreactor.ipc.netty
は、 this answerとともに動作するはずです。
体を記録したくない場合、これは本当に簡単です。
Application.propertiesに次を追加します。
logging.level.org.springframework.web.reactive.function.client.ExchangeFunctions=TRACE
spring.http.log-request-details=true
2行目では、ヘッダーがログに含まれます。
Application.propertiesに次を追加します。
logging.level.org.springframework.web.reactive.function.client.ExchangeFunctions=TRACE
上記の2行目の代わりに、次のようなクラスを宣言する必要があります。
@Configuration
static class LoggingCodecConfig {
@Bean
@Order(0)
public CodecCustomizer loggingCodecCustomizer() {
return (configurer) -> configurer.defaultCodecs()
.enableLoggingRequestDetails(true);
}
}
このブライアンクロゼルの回答 の礼儀
このようにSpring WebClientを作成すると、盗聴オプションが有効になり、盗聴するように要求することで、nettyに要求/応答のログを記録させることができます。
WebClient webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create().wiretap(true)
))
.build()
そして、あなたのロギングのセットアップがあります:
logging.level.reactor.netty.http.client.HttpClient: DEBUG
これにより、要求/応答のすべて(本文を含む)がログに記録されますが、この形式はHTTPに固有のものではないため、読みにくくなっています。