Logging improvements for WebFlux
Issue: SPR-16898
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,8 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -37,6 +39,8 @@ import org.springframework.util.MimeType;
|
||||
*/
|
||||
public abstract class AbstractDecoder<T> implements Decoder<T> {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final List<MimeType> decodableMimeTypes;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,10 @@ package org.springframework.core.codec;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -32,6 +36,8 @@ import org.springframework.util.MimeType;
|
||||
*/
|
||||
public abstract class AbstractEncoder<T> implements Encoder<T> {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final List<MimeType> encodableMimeTypes;
|
||||
|
||||
|
||||
@@ -53,4 +59,17 @@ public abstract class AbstractEncoder<T> implements Encoder<T> {
|
||||
return this.encodableMimeTypes.stream().anyMatch(candidate -> candidate.isCompatibleWith(mimeType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to obtain the logger to use from the Map of hints, or fall
|
||||
* back on the default logger. This may be used for example to override
|
||||
* logging, e.g. for a multipart request where the full map of part values
|
||||
* has already been logged.
|
||||
* @param hints the hints passed to the encode method
|
||||
* @return the logger to use
|
||||
* @since 5.1
|
||||
*/
|
||||
protected Log getLogger(@Nullable Map<String, Object> hints) {
|
||||
return hints != null ? ((Log) hints.getOrDefault(Log.class.getName(), logger)) : logger;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -53,6 +53,9 @@ public class ByteArrayDecoder extends AbstractDataBufferDecoder<byte[]> {
|
||||
byte[] result = new byte[dataBuffer.readableByteCount()];
|
||||
dataBuffer.read(result);
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Read " + result.length + " bytes");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.core.codec;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
@@ -52,7 +53,14 @@ public class ByteArrayEncoder extends AbstractEncoder<byte[]> {
|
||||
DataBufferFactory bufferFactory, ResolvableType elementType, @Nullable MimeType mimeType,
|
||||
@Nullable Map<String, Object> hints) {
|
||||
|
||||
return Flux.from(inputStream).map(bufferFactory::wrap);
|
||||
return Flux.from(inputStream).map(bytes -> {
|
||||
DataBuffer dataBuffer = bufferFactory.wrap(bytes);
|
||||
Log logger = getLogger(hints);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Writing " + dataBuffer.readableByteCount() + " bytes");
|
||||
}
|
||||
return dataBuffer;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -52,10 +52,14 @@ public class ByteBufferDecoder extends AbstractDataBufferDecoder<ByteBuffer> {
|
||||
protected ByteBuffer decodeDataBuffer(DataBuffer dataBuffer, ResolvableType elementType,
|
||||
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
|
||||
ByteBuffer copy = ByteBuffer.allocate(dataBuffer.readableByteCount());
|
||||
int byteCount = dataBuffer.readableByteCount();
|
||||
ByteBuffer copy = ByteBuffer.allocate(byteCount);
|
||||
copy.put(dataBuffer.asByteBuffer());
|
||||
copy.flip();
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Read " + byteCount + " bytes");
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.core.codec;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
@@ -53,7 +54,14 @@ public class ByteBufferEncoder extends AbstractEncoder<ByteBuffer> {
|
||||
DataBufferFactory bufferFactory, ResolvableType elementType, @Nullable MimeType mimeType,
|
||||
@Nullable Map<String, Object> hints) {
|
||||
|
||||
return Flux.from(inputStream).map(bufferFactory::wrap);
|
||||
return Flux.from(inputStream).map(byteBuffer -> {
|
||||
DataBuffer dataBuffer = bufferFactory.wrap(byteBuffer);
|
||||
Log logger = getLogger(hints);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Writing " + dataBuffer.readableByteCount() + " bytes");
|
||||
}
|
||||
return dataBuffer;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
@@ -65,6 +66,10 @@ public class CharSequenceEncoder extends AbstractEncoder<CharSequence> {
|
||||
Charset charset = getCharset(mimeType);
|
||||
|
||||
return Flux.from(inputStream).map(charSequence -> {
|
||||
Log logger = getLogger(hints);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Writing '" + charSequence + "'");
|
||||
}
|
||||
CharBuffer charBuffer = CharBuffer.wrap(charSequence);
|
||||
ByteBuffer byteBuffer = charset.encode(charBuffer);
|
||||
return bufferFactory.wrap(byteBuffer);
|
||||
|
||||
@@ -62,6 +62,9 @@ public class DataBufferDecoder extends AbstractDataBufferDecoder<DataBuffer> {
|
||||
protected DataBuffer decodeDataBuffer(DataBuffer buffer, ResolvableType elementType,
|
||||
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Read " + buffer.readableByteCount() + " bytes");
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.core.codec;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
@@ -52,7 +53,14 @@ public class DataBufferEncoder extends AbstractEncoder<DataBuffer> {
|
||||
DataBufferFactory bufferFactory, ResolvableType elementType, @Nullable MimeType mimeType,
|
||||
@Nullable Map<String, Object> hints) {
|
||||
|
||||
return Flux.from(inputStream);
|
||||
Flux<DataBuffer> flux = Flux.from(inputStream);
|
||||
|
||||
Log logger = getLogger(hints);
|
||||
if (logger.isDebugEnabled()) {
|
||||
flux = flux.doOnNext(buffer -> logger.debug("Writing " + buffer.readableByteCount() + " bytes"));
|
||||
}
|
||||
|
||||
return flux;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -72,6 +72,10 @@ public class ResourceDecoder extends AbstractDataBufferDecoder<Resource> {
|
||||
Class<?> clazz = elementType.getRawClass();
|
||||
Assert.state(clazz != null, "No resource class");
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Read " + bytes.length + " bytes");
|
||||
}
|
||||
|
||||
if (InputStreamResource.class == clazz) {
|
||||
return new InputStreamResource(new ByteArrayInputStream(bytes));
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.core.codec;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
@@ -65,6 +66,11 @@ public class ResourceEncoder extends AbstractSingleValueEncoder<Resource> {
|
||||
protected Flux<DataBuffer> encode(Resource resource, DataBufferFactory dataBufferFactory,
|
||||
ResolvableType type, @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
|
||||
Log logger = getLogger(hints);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Writing [" + resource + "]");
|
||||
}
|
||||
|
||||
return DataBufferUtils.read(resource, dataBufferFactory, this.bufferSize);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import java.util.OptionalLong;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -81,7 +82,7 @@ public class ResourceRegionEncoder extends AbstractEncoder<ResourceRegion> {
|
||||
|
||||
if (inputStream instanceof Mono) {
|
||||
return ((Mono<? extends ResourceRegion>) inputStream)
|
||||
.flatMapMany(region -> writeResourceRegion(region, bufferFactory));
|
||||
.flatMapMany(region -> writeResourceRegion(region, bufferFactory, hints));
|
||||
}
|
||||
else {
|
||||
Assert.notNull(hints, "'hints' must not be null");
|
||||
@@ -96,7 +97,7 @@ public class ResourceRegionEncoder extends AbstractEncoder<ResourceRegion> {
|
||||
concatMap(region ->
|
||||
Flux.concat(
|
||||
getRegionPrefix(bufferFactory, startBoundary, contentType, region),
|
||||
writeResourceRegion(region, bufferFactory)
|
||||
writeResourceRegion(region, bufferFactory, hints)
|
||||
));
|
||||
return Flux.concat(regions, getRegionSuffix(bufferFactory, boundaryString));
|
||||
}
|
||||
@@ -112,11 +113,20 @@ public class ResourceRegionEncoder extends AbstractEncoder<ResourceRegion> {
|
||||
);
|
||||
}
|
||||
|
||||
private Flux<DataBuffer> writeResourceRegion(ResourceRegion region, DataBufferFactory bufferFactory) {
|
||||
private Flux<DataBuffer> writeResourceRegion(
|
||||
ResourceRegion region, DataBufferFactory bufferFactory, @Nullable Map<String, Object> hints) {
|
||||
|
||||
Resource resource = region.getResource();
|
||||
long position = region.getPosition();
|
||||
long count = region.getCount();
|
||||
|
||||
Log logger = getLogger(hints);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Writing region " + position + "-" + (position + count) + " of [" + resource + "]");
|
||||
}
|
||||
|
||||
Flux<DataBuffer> in = DataBufferUtils.read(resource, position, bufferFactory, this.bufferSize);
|
||||
return DataBufferUtils.takeUntilByteCount(in, region.getCount());
|
||||
return DataBufferUtils.takeUntilByteCount(in, count);
|
||||
}
|
||||
|
||||
private Flux<DataBuffer> getRegionSuffix(DataBufferFactory bufferFactory, String boundaryString) {
|
||||
|
||||
@@ -205,7 +205,11 @@ public class StringDecoder extends AbstractDataBufferDecoder<String> {
|
||||
Charset charset = getCharset(mimeType);
|
||||
CharBuffer charBuffer = charset.decode(dataBuffer.asByteBuffer());
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
return charBuffer.toString();
|
||||
String value = charBuffer.toString();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Decoded '" + "'");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private static Charset getCharset(@Nullable MimeType mimeType) {
|
||||
|
||||
Reference in New Issue
Block a user