我正在尝试使用Spring 5 WebClient记录请求。你知道我怎样才能做到吗?
(我使用的是Spring5和Spring靴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;
}
您不一定需要运行自己的记录器,reactor。ipc。内蒂。频道ChannelOperationsHandler为您执行此操作。只需为该类配置日志记录系统,以便在调试级别进行日志记录:
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
减少bug的一种方法是尽可能不编写代码。
十一月2018:
使用<代码>spring webflux:5.1.2。发布后,上述操作将不再有效。请使用以下选项:
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
要记录标题或表单正文,请将上述设置为跟踪级别;然而,这还不够:
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应该和这个答案一起工作。
您可以通过要求它进行窃听来记录请求/响应,如果您像这样创建Spring WebClient,那么它会启用窃听选项。
WebClient webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create().wiretap(true)
))
.build()
然后进行日志记录设置:
logging.level.reactor.netty.http.client.HttpClient: DEBUG
这将记录请求/响应的所有内容(包括主体),但格式并不特定于HTTP,因此不太易读。
您可以使用ExchangeFilterFunction轻松完成此操作
使用网络客户端创建网络客户端时,只需添加自定义日志请求过滤器。生成器。
下面是此类过滤器的示例,以及如何将其添加到Web客户端。
@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. This method is NOT part of the answer
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。发送(“获取”) 和日志消息。
输出示例:
Request: GET https://httpbin.org/get?param=value
header1=value1
header2=value2
编辑
一些人在评论中指出,block()
是不好的做法。我想澄清:block()
这里的调用只是为了演示。请求日志过滤器无论如何都会工作。您无需向代码中添加block()
,即可使ExchangeFilterFunction
正常工作。您可以使用WebClient以常规方式执行http调用,链接方法并返回堆栈上的Mono,直到有人订阅为止。答案中唯一相关的部分是过滤。您可以完全忽略send()
方法-它不是解决方案的一部分-它只是演示了过滤器的工作原理。
一些人还问如何记录回应。要记录响应,可以编写另一个ExchangeFilterFunction,并将其添加到WebClient。您可以使用ExchangeFilterFunction。响应处理器的帮助程序的方法与ExchangeFilterFunction的方法相同。使用了请求处理器(ofRequestProcessor)。您可以使用ClientResponse的方法获取标题/cookie等。
// This method returns filter function which will log response data
private static ExchangeFilterFunction logResponse() {
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
log.info("Response status: {}", clientResponse.statusCode());
clientResponse.headers().asHttpHeaders().forEach((name, values) -> values.forEach(value -> log.info("{}={}", name, value)));
return Mono.just(clientResponse);
});
}
不要忘记将其添加到您的网络客户端:
.filter(logResponse())
但要小心,不要试图读取过滤器中的响应正文。由于它的流性质,在没有某种缓冲包装器的情况下,身体只能消费一次。因此,如果您将在过滤器中读取它,那么您将无法在订阅服务器中读取它。
如果确实需要记录正文,可以使用底层(Netty)来完成此操作。请参阅Matthew Buckett的答案以了解想法。
我正在使用Fiegn创建一个REST客户端。我已经让我的调用正常工作了,但我想记录回退方法调用的异常which tigger 代码如下: 发生异常时可以调用回退方法,但记录注意事项。 如何记录触发调用的回退方法的异常? 如connectionTimeoutException。
我有一个简单的Java程序,它使用SpringWebClient发送多个请求。每个都返回一个mono,我使用的是response。subscribe()以检查结果。 但是,我的主执行线程在处理所有请求之前完成,除非我添加一个长线程。睡眠()。 对于CompletableFutures,您可以使用:CompletableFuture。allOf(期货)。join(); 有没有办法等待所有单声道的完成
我将事件发送到AWS Kinesis,这些事件由AWS lambda函数处理。但是,如果lambda抛出一些错误,则不会丢弃记录,并且会一次又一次地进行处理,从而阻止处理新记录。 我宁愿跳过错误的记录,消化新的记录。我不知道该怎么做。 lambda函数捕获任何异常,因此不应给出任何执行错误。 下面是python中的片段。 我知道lambda应该在“保留”期间重试(默认为24小时),但我希望放弃并最
我正在调用Apache Camel XML DSL中的Javascript文件,该文件在Apache ServiceMix中运行,如下所示: 我想在myJavascript中记录一条消息。这样消息就会显示在主Camel上下文日志中。 这里的Camel文档表示传递了CamelContext Java对象。我希望它能为记录器提供一个getter,这样我就可以在脚本中做这样的事情: 然而,这里并没有提到
Java16引入了记录,这有助于在编写携带不可变数据的类时减少样板代码。当我尝试将记录用作bean时,我得到以下错误消息: 如何将记录用作?
但是Crawler4J中有一个记录器。 如何禁用记录器内部爬行4J库?