2017-09-11 2 views
6

Ich versuche, Anfrage zu schreiben, die ich mit einem Spring 5 WebClient mache, irgendeine Idee, wie ich das erreichen könnte?wie man Spring 5 WebClient-Anruf protokolliert

(Ich bin mit Feder 5 und Spring-Boot 2)

Code aussehen, das im Moment.

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; 
     } 
+0

Können Sie den Code teilen, den Sie gerade haben? –

+0

@BrianClozel hier ist es – Seb

+0

Danke! Könnten Sie auch ein Beispiel dafür geben, was Sie gerne protokollieren würden? Die Anfrage-URI? –

Antwort

4

Sie können es leicht ExchangeFilterFunction Sie mit

Nur den benutzerdefinierten logRequest Filter hinzufügen, wenn Sie Ihre WebClientWebClient.Builder Verwendung erstellen.

Hier ist das Beispiel eines solchen Filters und wie man es zur WebClient hinzufügt.

@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); 
     }); 
    } 

} 

Dann rufen Sie einfach myClient.send("get"); und Protokollmeldungen sollten da sein.

Ausgabebeispiel:

Request: GET https://httpbin.org/get?param=value 
header1=value1 
header2=value2 
+0

perfekte Lösung !! – Seb

+0

IMO, Aufruf von 'block()' vereitelt den Zweck der Verwendung von Webclient. Wir können die Anfrage mit einem Filter protokollieren, aber nicht sicher, wie wir die Antwort von einer 'Mono ' ohne Blockierung protokollieren. –

+0

@PavanKumar Der 'block()' Aufruf hier dient nur dem Zweck der Demo. Der Request-Logging-Filter funktioniert trotzdem. Um die Antwort zu protokollieren, können Sie eine andere [ExchangeFilterFunction] schreiben (https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/function/client/ExchangeFilterFunction.html# ofResponseProcessor-java.util.function.Function-) und protokollieren die Antwort. Aber seien Sie vorsichtig, wenn Sie den Antworttext protokollieren - wegen der Stream-Natur kann er nur einmal ohne Wrapper konsumiert werden. – djxak

2

Sie müssen nicht unbedingt benötigen, um Ihre eigenen Logger zu rollen, reactor.ipc.netty.channel.ChannelOperationsHandler macht es für Sie. Ihr Logging-System einfach konfigurieren für diese Klasse auf DEBUG Ebene zu protokollieren:

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 

Eine Möglichkeit, wenige Fehler haben, ist nicht, Code zu schreiben, wann immer möglich.

+0

Ich bevorzuge diese Lösung in begrenzten und kontrollierten Umgebungen als eine einfachere Möglichkeit zum Debuggen. Dies wird nicht immer empfohlen, da dadurch möglicherweise vertrauliche Informationen in den Kopfzeilen usw. angezeigt werden. Wenn ein benutzerdefinierter Filter eingesteckt ist, besteht die Möglichkeit, solche vertraulichen Informationen zu analysieren und auszublenden. –

+0

@PavanKumar Jede Art von Protokollierungsübertragung kann empfindliche Header wie "Autorisierung" offen legen. Das OP hat nicht darum gebeten, sie zu verstecken, aber * wenn * das eine Voraussetzung ist, * dann kann * Code geschrieben werden. Normalerweise ist es zulässig, solche Header auf DEBUG-Ebene zu protokollieren. –

Verwandte Themen