From 62eb0f742861df6122bba8812449e92d07948ce1 Mon Sep 17 00:00:00 2001 From: maryarm Date: Wed, 28 Aug 2019 20:00:29 +0430 Subject: [PATCH 1/3] BAEL-3009: Logging Spring WebClient calls --- spring-5-reactive-client/pom.xml | 12 +- .../WebClientLoggingIntegrationTest.java | 150 ++++++++++++++++++ .../reactive/logging/filters/LogFilters.java | 33 ++++ .../logging/jetty/RequestLogEnhancer.java | 88 ++++++++++ .../reactive/logging/netty/CustomLogger.java | 37 +++++ .../src/test/resources/logback-test.xml | 8 +- 6 files changed, 324 insertions(+), 4 deletions(-) create mode 100644 spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java create mode 100644 spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java create mode 100644 spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java create mode 100644 spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java diff --git a/spring-5-reactive-client/pom.xml b/spring-5-reactive-client/pom.xml index 1b71815eb4..5e9fdd9fb4 100644 --- a/spring-5-reactive-client/pom.xml +++ b/spring-5-reactive-client/pom.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-5-reactive-client spring-5-reactive-client @@ -56,7 +56,6 @@ - org.springframework.boot spring-boot-devtools @@ -89,6 +88,14 @@ org.projectlombok lombok + + + + org.eclipse.jetty + jetty-reactive-httpclient + ${jetty-reactive-httpclient.version} + test + @@ -110,6 +117,7 @@ 1.0 1.0 4.1 + 1.0.3 diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java new file mode 100644 index 0000000000..bb88502132 --- /dev/null +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java @@ -0,0 +1,150 @@ +package com.baeldung.reactive.logging; + +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.core.Appender; +import com.baeldung.reactive.logging.filters.LogFilters; +import com.baeldung.reactive.logging.jetty.RequestLogEnhancer; +import com.baeldung.reactive.logging.netty.CustomLogger; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.net.URI; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.LoggerFactory; +import org.springframework.http.client.reactive.JettyClientHttpConnector; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.netty.channel.BootstrapHandlers; +import reactor.netty.http.client.HttpClient; + +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + + +public class WebClientLoggingIntegrationTest { + + @AllArgsConstructor + @Data + class Post { + private String title; + private String body; + private int userId; + } + + private Appender jettyAppender; + private Appender nettyAppender; + private Appender mockAppender; + private String sampleUrl = "https://jsonplaceholder.typicode.com/posts"; + + private Post post; + private String sampleResponseBody; + + @BeforeEach + private void setup() throws Exception { + + post = new Post("Learn WebClient logging with Baeldung!", "", 1); + sampleResponseBody = new ObjectMapper().writeValueAsString(post); + + ch.qos.logback.classic.Logger jetty = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.baeldung.reactive.logging.jetty"); + jettyAppender = mock(Appender.class); + when(jettyAppender.getName()).thenReturn("com.baeldung.reactive.logging.jetty"); + jetty.addAppender(jettyAppender); + + ch.qos.logback.classic.Logger netty = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("reactor.netty.http.client"); + nettyAppender = mock(Appender.class); + when(nettyAppender.getName()).thenReturn("reactor.netty.http.client"); + netty.addAppender(nettyAppender); + + ch.qos.logback.classic.Logger test = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.baeldung.reactive"); + mockAppender = mock(Appender.class); + when(mockAppender.getName()).thenReturn("com.baeldung.reactive"); + test.addAppender(mockAppender); + + } + + @Test + public void givenJettyHttpClient_whenEndpointIsConsumed_thenRequestAndResponseBodyShouldBeLogged() { + SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); + org.eclipse.jetty.client.HttpClient httpClient = new org.eclipse.jetty.client.HttpClient(sslContextFactory) { + @Override + public Request newRequest(URI uri) { + Request request = super.newRequest(uri); + return new RequestLogEnhancer().enhance(request); + } + }; + + WebClient + .builder() + .clientConnector(new JettyClientHttpConnector(httpClient)) + .build() + .post() + .uri(sampleUrl) + .body(BodyInserters.fromObject(post)) + .retrieve() + .bodyToMono(String.class) + .block(); + + verify(jettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains(sampleResponseBody))); + } + + @Test + public void givenNettyHttpClientWithWiretap_whenEndpointIsConsumed_thenRequestAndResponseBodyShouldBeLogged() { + + reactor.netty.http.client.HttpClient httpClient = HttpClient + .create() + .wiretap(true); + WebClient + .builder() + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .build() + .post() + .uri(sampleUrl) + .body(BodyInserters.fromObject(post)) + .exchange() + .block(); + verify(nettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains("00000300"))); + } + + @Test + public void givenNettyHttpClientWithCustomLogger_whenEndpointIsConsumed_thenRequestAndResponseBodyShouldBeLogged() { + + reactor.netty.http.client.HttpClient httpClient = HttpClient + .create() + .tcpConfiguration(tcpClient -> tcpClient.bootstrap(b -> BootstrapHandlers.updateLogSupport(b, new CustomLogger(HttpClient.class)))); + WebClient + .builder() + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .build() + .post() + .uri(sampleUrl) + .body(BodyInserters.fromObject(post)) + .exchange() + .block(); + verify(nettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains(sampleResponseBody))); + } + + @Test + public void givenDefaultHttpClientWithString_whenEndpointIsConsumed_thenRequestAndResponseLogged() { + WebClient + .builder() + .filters(exchangeFilterFunctions -> { + exchangeFilterFunctions.addAll(LogFilters.prepareFilters()); + }) + .build() + .post() + .uri(sampleUrl) + .body(BodyInserters.fromObject(post)) + .exchange() + .block(); + + verify(mockAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains("domain=.typicode.com;"))); + } + + +} diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java new file mode 100644 index 0000000000..8bb4c2aecd --- /dev/null +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java @@ -0,0 +1,33 @@ +package com.baeldung.reactive.logging.filters; + +import java.util.Arrays; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import reactor.core.publisher.Mono; + +@Slf4j +public class LogFilters { + public static List prepareFilters(){ + return Arrays.asList(ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { + if ( log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("Request: \n").append(clientRequest.method()).append(" ").append(clientRequest.url()); + clientRequest + .headers() + .forEach((name, values) -> values.forEach(value -> sb.append("\n").append(name).append(":").append(value))); + log.debug(sb.toString()); + } + return Mono.just(clientRequest); + }), ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { + if ( log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("Response: \n").append("Status: ").append(clientResponse.rawStatusCode()); + clientResponse + .headers() + .asHttpHeaders() + .forEach((key, value1) -> value1.forEach(value -> sb.append("\n").append(key).append(":").append(value))); + log.debug(sb.toString()); + } + return Mono.just(clientResponse); + })); + } +} diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java new file mode 100644 index 0000000000..334faf2c91 --- /dev/null +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java @@ -0,0 +1,88 @@ +package com.baeldung.reactive.logging.jetty; + +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Locale; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpHeader; + +@Slf4j +public class RequestLogEnhancer { + + public Request enhance(Request request) { + StringBuilder group = new StringBuilder(); + request.onRequestBegin(theRequest -> group + .append("Request ") + .append(theRequest.getMethod()) + .append(" ") + .append(theRequest.getURI()) + .append("\n")); + request.onRequestHeaders(theRequest -> { + for (HttpField header : theRequest.getHeaders()) + group + .append(header) + .append("\n"); + }); + request.onRequestContent((theRequest, content) -> group.append(toString(content, getCharset(theRequest.getHeaders())))); + request.onRequestSuccess(theRequest -> { + log.debug(group.toString()); + group.delete(0, group.length()); + }); + group.append("\n"); + request.onResponseBegin(theResponse -> { + group + .append("Response \n ") + .append(theResponse.getVersion()) + .append(" ") + .append(theResponse.getStatus()); + if (theResponse.getReason() != null) group + .append(" ") + .append(theResponse.getReason()); + group.append("\n"); + }); + request.onResponseHeaders(theResponse -> { + for (HttpField header : theResponse.getHeaders()) + group + .append(header) + .append("\n"); + }); + request.onResponseContent((theResponse, content) -> group.append(toString(content, getCharset(theResponse.getHeaders())))); + request.onResponseSuccess(theResponse -> { + log.debug(group.toString()); + }); + return request; + } + + + private String toString(ByteBuffer buffer, Charset charset) + { + byte[] bytes; + if (buffer.hasArray()) { + bytes = new byte[buffer.capacity()]; + System.arraycopy(buffer.array(), 0, bytes, 0, buffer.capacity() ); + } + else + { + bytes = new byte[buffer.remaining()]; + buffer.get(bytes, 0, bytes.length); + } + return new String(bytes, charset); + } + + + private Charset getCharset(HttpFields headers) { + String contentType = headers.get(HttpHeader.CONTENT_TYPE); + if (contentType == null) return StandardCharsets.UTF_8; + String[] tokens = contentType + .toLowerCase(Locale.US) + .split("charset="); + if (tokens.length != 2) return StandardCharsets.UTF_8; + String encoding = tokens[1].replaceAll("[;\"]", ""); + return Charset.forName(encoding); + } +} + diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java new file mode 100644 index 0000000000..df7c65f33f --- /dev/null +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java @@ -0,0 +1,37 @@ +package com.baeldung.reactive.logging.netty; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.logging.LoggingHandler; +import io.netty.util.internal.PlatformDependent; +import java.nio.charset.Charset; + +public class CustomLogger extends LoggingHandler { + public CustomLogger(Class clazz) { + super(clazz); + } + + @Override + protected String format(ChannelHandlerContext ctx, String eventName, Object arg) { + if (arg instanceof ByteBuf) { + ByteBuf msg = (ByteBuf) arg; + return decodeString(msg, msg.readerIndex(), msg.readableBytes(), Charset.defaultCharset()); + } + return ""; + } + + private String decodeString(ByteBuf src, int readerIndex, int len, Charset charset) { + if (len == 0) return ""; + byte[] array; + int offset; + if (src.hasArray()) { + array = src.array(); + offset = src.arrayOffset() + readerIndex; + } else { + array = PlatformDependent.allocateUninitializedArray(Math.max(len, 1024)); + offset = 0; + src.getBytes(readerIndex, array, 0, len); + } + return new String(array, offset, len, charset); + } +} diff --git a/spring-5-reactive-client/src/test/resources/logback-test.xml b/spring-5-reactive-client/src/test/resources/logback-test.xml index 7072369b8d..42cb0865c5 100644 --- a/spring-5-reactive-client/src/test/resources/logback-test.xml +++ b/spring-5-reactive-client/src/test/resources/logback-test.xml @@ -6,11 +6,15 @@ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - + + + + + - + \ No newline at end of file From 52a90adf92e086cab6d2900064ed257f9ca070d8 Mon Sep 17 00:00:00 2001 From: maryarm Date: Thu, 29 Aug 2019 16:25:30 +0430 Subject: [PATCH 2/3] BAEL-3009: Apply review notes and formatting standards. --- spring-5-reactive-client/pom.xml | 2 +- .../WebClientLoggingIntegrationTest.java | 4 +- .../reactive/logging/filters/LogFilters.java | 41 +++++++++++++---- .../logging/jetty/RequestLogEnhancer.java | 46 ++++++++++--------- .../reactive/logging/netty/CustomLogger.java | 35 ++++++++------ 5 files changed, 80 insertions(+), 48 deletions(-) diff --git a/spring-5-reactive-client/pom.xml b/spring-5-reactive-client/pom.xml index 5e9fdd9fb4..70771f6832 100644 --- a/spring-5-reactive-client/pom.xml +++ b/spring-5-reactive-client/pom.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-5-reactive-client spring-5-reactive-client diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java index bb88502132..d5f1ef77a0 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java @@ -116,7 +116,9 @@ public class WebClientLoggingIntegrationTest { reactor.netty.http.client.HttpClient httpClient = HttpClient .create() - .tcpConfiguration(tcpClient -> tcpClient.bootstrap(b -> BootstrapHandlers.updateLogSupport(b, new CustomLogger(HttpClient.class)))); + .tcpConfiguration( + tc -> tc.bootstrap( + b -> BootstrapHandlers.updateLogSupport(b, new CustomLogger(HttpClient.class)))); WebClient .builder() .clientConnector(new ReactorClientHttpConnector(httpClient)) diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java index 8bb4c2aecd..c1c3d3e895 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java @@ -8,26 +8,47 @@ import reactor.core.publisher.Mono; @Slf4j public class LogFilters { - public static List prepareFilters(){ - return Arrays.asList(ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { - if ( log.isDebugEnabled()) { - StringBuilder sb = new StringBuilder("Request: \n").append(clientRequest.method()).append(" ").append(clientRequest.url()); + public static List prepareFilters() { + return Arrays.asList(logRequest(), logResponse()); + } + + private static ExchangeFilterFunction logRequest() { + return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { + if (log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("Request: \n") + .append(clientRequest.method()) + .append(" ") + .append(clientRequest.url()); clientRequest .headers() - .forEach((name, values) -> values.forEach(value -> sb.append("\n").append(name).append(":").append(value))); + .forEach((name, values) -> values.forEach(value -> sb + .append("\n") + .append(name) + .append(":") + .append(value))); log.debug(sb.toString()); } return Mono.just(clientRequest); - }), ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { - if ( log.isDebugEnabled()) { - StringBuilder sb = new StringBuilder("Response: \n").append("Status: ").append(clientResponse.rawStatusCode()); + }); + } + + private static ExchangeFilterFunction logResponse() { + return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { + if (log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("Response: \n") + .append("Status: ") + .append(clientResponse.rawStatusCode()); clientResponse .headers() .asHttpHeaders() - .forEach((key, value1) -> value1.forEach(value -> sb.append("\n").append(key).append(":").append(value))); + .forEach((key, value1) -> value1.forEach(value -> sb + .append("\n") + .append(key) + .append(":") + .append(value))); log.debug(sb.toString()); } return Mono.just(clientResponse); - })); + }); } } diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java index 334faf2c91..ac333feb6c 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java @@ -27,7 +27,9 @@ public class RequestLogEnhancer { .append(header) .append("\n"); }); - request.onRequestContent((theRequest, content) -> group.append(toString(content, getCharset(theRequest.getHeaders())))); + request.onRequestContent((theRequest, content) -> { + group.append(toString(content, getCharset(theRequest.getHeaders()))); + }); request.onRequestSuccess(theRequest -> { log.debug(group.toString()); group.delete(0, group.length()); @@ -35,13 +37,15 @@ public class RequestLogEnhancer { group.append("\n"); request.onResponseBegin(theResponse -> { group - .append("Response \n ") + .append("Response \n") .append(theResponse.getVersion()) .append(" ") .append(theResponse.getStatus()); - if (theResponse.getReason() != null) group - .append(" ") - .append(theResponse.getReason()); + if (theResponse.getReason() != null) { + group + .append(" ") + .append(theResponse.getReason()); + } group.append("\n"); }); request.onResponseHeaders(theResponse -> { @@ -50,39 +54,39 @@ public class RequestLogEnhancer { .append(header) .append("\n"); }); - request.onResponseContent((theResponse, content) -> group.append(toString(content, getCharset(theResponse.getHeaders())))); + request.onResponseContent((theResponse, content) -> { + group.append(toString(content, getCharset(theResponse.getHeaders()))); + }); request.onResponseSuccess(theResponse -> { log.debug(group.toString()); }); return request; } - - private String toString(ByteBuffer buffer, Charset charset) - { + private String toString(ByteBuffer buffer, Charset charset) { byte[] bytes; if (buffer.hasArray()) { bytes = new byte[buffer.capacity()]; - System.arraycopy(buffer.array(), 0, bytes, 0, buffer.capacity() ); - } - else - { + System.arraycopy(buffer.array(), 0, bytes, 0, buffer.capacity()); + } else { bytes = new byte[buffer.remaining()]; buffer.get(bytes, 0, bytes.length); } return new String(bytes, charset); } - private Charset getCharset(HttpFields headers) { String contentType = headers.get(HttpHeader.CONTENT_TYPE); - if (contentType == null) return StandardCharsets.UTF_8; - String[] tokens = contentType - .toLowerCase(Locale.US) - .split("charset="); - if (tokens.length != 2) return StandardCharsets.UTF_8; - String encoding = tokens[1].replaceAll("[;\"]", ""); - return Charset.forName(encoding); + if (contentType != null) { + String[] tokens = contentType + .toLowerCase(Locale.US) + .split("charset="); + if (tokens.length == 2) { + String encoding = tokens[1].replaceAll("[;\"]", ""); + return Charset.forName(encoding); + } + } + return StandardCharsets.UTF_8; } } diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java index df7c65f33f..529549f99b 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java @@ -3,35 +3,40 @@ package com.baeldung.reactive.logging.netty; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.logging.LoggingHandler; -import io.netty.util.internal.PlatformDependent; import java.nio.charset.Charset; +import static io.netty.util.internal.PlatformDependent.allocateUninitializedArray; +import static java.lang.Math.max; +import static java.nio.charset.Charset.defaultCharset; + public class CustomLogger extends LoggingHandler { public CustomLogger(Class clazz) { super(clazz); } @Override - protected String format(ChannelHandlerContext ctx, String eventName, Object arg) { + protected String format(ChannelHandlerContext ctx, String event, Object arg) { if (arg instanceof ByteBuf) { ByteBuf msg = (ByteBuf) arg; - return decodeString(msg, msg.readerIndex(), msg.readableBytes(), Charset.defaultCharset()); + return decode(msg, msg.readerIndex(), msg.readableBytes(), defaultCharset()); } return ""; } - private String decodeString(ByteBuf src, int readerIndex, int len, Charset charset) { - if (len == 0) return ""; - byte[] array; - int offset; - if (src.hasArray()) { - array = src.array(); - offset = src.arrayOffset() + readerIndex; - } else { - array = PlatformDependent.allocateUninitializedArray(Math.max(len, 1024)); - offset = 0; - src.getBytes(readerIndex, array, 0, len); + private String decode(ByteBuf src, int readerIndex, int len, Charset charset) { + if (len != 0) { + byte[] array; + int offset; + if (src.hasArray()) { + array = src.array(); + offset = src.arrayOffset() + readerIndex; + } else { + array = allocateUninitializedArray(max(len, 1024)); + offset = 0; + src.getBytes(readerIndex, array, 0, len); + } + return new String(array, offset, len, charset); } - return new String(array, offset, len, charset); + return ""; } } From e7e2c0a8a6a650dbd36cc0ae559abe4c301d5489 Mon Sep 17 00:00:00 2001 From: maryarm Date: Thu, 5 Sep 2019 21:00:26 +0430 Subject: [PATCH 3/3] BAEL-3009: Logging Spring WebClient calls. -Review notes applied --- .../logging/WebClientLoggingIntegrationTest.java | 14 ++++++++------ .../reactive/logging/jetty/RequestLogEnhancer.java | 7 ++++--- .../reactive/logging/netty/CustomLogger.java | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java index d5f1ef77a0..95c63f267f 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java @@ -3,7 +3,6 @@ package com.baeldung.reactive.logging; import ch.qos.logback.classic.spi.LoggingEvent; import ch.qos.logback.core.Appender; import com.baeldung.reactive.logging.filters.LogFilters; -import com.baeldung.reactive.logging.jetty.RequestLogEnhancer; import com.baeldung.reactive.logging.netty.CustomLogger; import com.fasterxml.jackson.databind.ObjectMapper; import java.net.URI; @@ -21,6 +20,7 @@ import org.springframework.web.reactive.function.client.WebClient; import reactor.netty.channel.BootstrapHandlers; import reactor.netty.http.client.HttpClient; +import static com.baeldung.reactive.logging.jetty.RequestLogEnhancer.enhance; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -69,13 +69,13 @@ public class WebClientLoggingIntegrationTest { } @Test - public void givenJettyHttpClient_whenEndpointIsConsumed_thenRequestAndResponseBodyShouldBeLogged() { + public void givenJettyHttpClient_whenEndpointIsConsumed_thenRequestAndResponseBodyLogged() { SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); org.eclipse.jetty.client.HttpClient httpClient = new org.eclipse.jetty.client.HttpClient(sslContextFactory) { @Override public Request newRequest(URI uri) { Request request = super.newRequest(uri); - return new RequestLogEnhancer().enhance(request); + return enhance(request); } }; @@ -94,7 +94,7 @@ public class WebClientLoggingIntegrationTest { } @Test - public void givenNettyHttpClientWithWiretap_whenEndpointIsConsumed_thenRequestAndResponseBodyShouldBeLogged() { + public void givenNettyHttpClientWithWiretap_whenEndpointIsConsumed_thenRequestAndResponseBodyLogged() { reactor.netty.http.client.HttpClient httpClient = HttpClient .create() @@ -108,11 +108,12 @@ public class WebClientLoggingIntegrationTest { .body(BodyInserters.fromObject(post)) .exchange() .block(); + verify(nettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains("00000300"))); } @Test - public void givenNettyHttpClientWithCustomLogger_whenEndpointIsConsumed_thenRequestAndResponseBodyShouldBeLogged() { + public void givenNettyHttpClientWithCustomLogger_whenEndpointIsConsumed_thenRequestAndResponseBodyLogged() { reactor.netty.http.client.HttpClient httpClient = HttpClient .create() @@ -128,11 +129,12 @@ public class WebClientLoggingIntegrationTest { .body(BodyInserters.fromObject(post)) .exchange() .block(); + verify(nettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains(sampleResponseBody))); } @Test - public void givenDefaultHttpClientWithString_whenEndpointIsConsumed_thenRequestAndResponseLogged() { + public void givenDefaultHttpClientWithFilter_whenEndpointIsConsumed_thenRequestAndResponseLogged() { WebClient .builder() .filters(exchangeFilterFunctions -> { diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java index ac333feb6c..43e3660743 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java @@ -13,7 +13,7 @@ import org.eclipse.jetty.http.HttpHeader; @Slf4j public class RequestLogEnhancer { - public Request enhance(Request request) { + public static Request enhance(Request request) { StringBuilder group = new StringBuilder(); request.onRequestBegin(theRequest -> group .append("Request ") @@ -63,7 +63,7 @@ public class RequestLogEnhancer { return request; } - private String toString(ByteBuffer buffer, Charset charset) { + private static String toString(ByteBuffer buffer, Charset charset) { byte[] bytes; if (buffer.hasArray()) { bytes = new byte[buffer.capacity()]; @@ -75,7 +75,7 @@ public class RequestLogEnhancer { return new String(bytes, charset); } - private Charset getCharset(HttpFields headers) { + private static Charset getCharset(HttpFields headers) { String contentType = headers.get(HttpHeader.CONTENT_TYPE); if (contentType != null) { String[] tokens = contentType @@ -88,5 +88,6 @@ public class RequestLogEnhancer { } return StandardCharsets.UTF_8; } + } diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java index 529549f99b..9f2a4d127f 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java @@ -20,7 +20,7 @@ public class CustomLogger extends LoggingHandler { ByteBuf msg = (ByteBuf) arg; return decode(msg, msg.readerIndex(), msg.readableBytes(), defaultCharset()); } - return ""; + return super.format(ctx, event, arg); } private String decode(ByteBuf src, int readerIndex, int len, Charset charset) {