Add LogFormatUtils
1. Helper method to eliminate duplication in formatting (de-)serialized values for logging introduced with prior commit #e62298. 2. Helper method for TRACE vs DEBUG logging with different details. Issue: SPR-17254
This commit is contained in:
@@ -28,6 +28,7 @@ import reactor.core.publisher.Flux;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
@@ -68,15 +69,11 @@ public final class CharSequenceEncoder extends AbstractEncoder<CharSequence> {
|
||||
Charset charset = getCharset(mimeType);
|
||||
|
||||
return Flux.from(inputStream).map(charSequence -> {
|
||||
if (logger.isDebugEnabled() && !Hints.isLoggingSuppressed(hints)) {
|
||||
String logPrefix = Hints.getLogPrefix(hints);
|
||||
String s = logPrefix + "Writing " + formatValue(charSequence, logger.isTraceEnabled());
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
if (!Hints.isLoggingSuppressed(hints)) {
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> {
|
||||
String formatted = LogFormatUtils.formatValue(charSequence, !traceOn);
|
||||
return Hints.getLogPrefix(hints) + "Writing " + formatted;
|
||||
});
|
||||
}
|
||||
CharBuffer charBuffer = CharBuffer.wrap(charSequence);
|
||||
ByteBuffer byteBuffer = charset.encode(charBuffer);
|
||||
@@ -95,14 +92,6 @@ public final class CharSequenceEncoder extends AbstractEncoder<CharSequence> {
|
||||
return charset;
|
||||
}
|
||||
|
||||
private String formatValue(@Nullable Object value, boolean logFullValue) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
String s = value instanceof CharSequence ? "\"" + value + "\"" : value.toString();
|
||||
return logFullValue || s.length() < 100 ? s : s.substring(0, 100) + " (truncated)...";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a {@code CharSequenceEncoder} that supports only "text/plain".
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MimeType;
|
||||
@@ -206,15 +207,10 @@ public final class StringDecoder extends AbstractDataBufferDecoder<String> {
|
||||
CharBuffer charBuffer = charset.decode(dataBuffer.asByteBuffer());
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
String value = charBuffer.toString();
|
||||
if (logger.isDebugEnabled()) {
|
||||
String s = Hints.getLogPrefix(hints) + "Decoded " + formatValue(value, logger.isTraceEnabled());
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
}
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> {
|
||||
String formatted = LogFormatUtils.formatValue(value, !traceOn);
|
||||
return Hints.getLogPrefix(hints) + "Decoded " + formatted;
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -227,14 +223,6 @@ public final class StringDecoder extends AbstractDataBufferDecoder<String> {
|
||||
}
|
||||
}
|
||||
|
||||
private String formatValue(@Nullable Object value, boolean logFullValue) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
String s = value instanceof CharSequence ? "\"" + value + "\"" : value.toString();
|
||||
return logFullValue || s.length() < 100 ? s : s.substring(0, 100) + " (truncated)...";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a {@code StringDecoder} for {@code "text/plain"}.
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.core.log;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Utility methods for formatting and logging messages.
|
||||
*
|
||||
* <p>Mainly for internal use within the framework with Apache Commons Logging,
|
||||
* typically in the form of the {@code spring-jcl} bridge but also compatible
|
||||
* with other Commons Logging bridges.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.1
|
||||
*/
|
||||
public final class LogFormatUtils {
|
||||
|
||||
private LogFormatUtils() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Format the given value via {@code toString()}, quoting it if it is a
|
||||
* {@link CharSequence}, and possibly truncating at 100 if limitLength is
|
||||
* set to true.
|
||||
* @param value the value to format
|
||||
* @param limitLength whether to truncate large formatted values (over 100).
|
||||
* @return the formatted value
|
||||
* @since 5.1
|
||||
*/
|
||||
public static String formatValue(@Nullable Object value, boolean limitLength) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
String s = value instanceof CharSequence ? "\"" + value + "\"" : value.toString();
|
||||
return limitLength && s.length() > 100 ? s.substring(0, 100) + " (truncated)..." : s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to log a message with different levels of detail (or different
|
||||
* messages) at TRACE vs DEBUG log levels. Effectively, a substitute for:
|
||||
* <pre class="code">
|
||||
* if (logger.isDebugEnabled()) {
|
||||
* String s = logger.isTraceEnabled() ? "..." : "...";
|
||||
* if (logger.isTraceEnabled()) {
|
||||
* logger.trace(s);
|
||||
* }
|
||||
* else {
|
||||
* logger.debug(s);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* @param logger the logger to use to log the message
|
||||
* @param messageFactory function that accepts a boolean set to the value
|
||||
* of {@link Log#isTraceEnabled()}.
|
||||
*/
|
||||
public static void traceDebug(Log logger, Function<Boolean, String> messageFactory) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
String logMessage = messageFactory.apply(logger.isTraceEnabled());
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(logMessage);
|
||||
}
|
||||
else {
|
||||
logger.debug(logMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.Hints;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ReactiveHttpInputMessage;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -114,18 +115,10 @@ public class FormHttpMessageReader extends LoggingCodecSupport
|
||||
}
|
||||
|
||||
private void logFormData(MultiValueMap<String, String> formData, Map<String, Object> hints) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
String s = Hints.getLogPrefix(hints) + "Read " +
|
||||
(isEnableLoggingRequestDetails() ?
|
||||
formatValue(formData, logger.isTraceEnabled()) :
|
||||
"form fields " + formData.keySet() + " (content masked)");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
}
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Read " +
|
||||
(isEnableLoggingRequestDetails() ?
|
||||
LogFormatUtils.formatValue(formData, !traceOn) :
|
||||
"form fields " + formData.keySet() + " (content masked)"));
|
||||
}
|
||||
|
||||
private Charset getMediaTypeCharset(@Nullable MediaType mediaType) {
|
||||
|
||||
@@ -31,6 +31,7 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.Hints;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ReactiveHttpOutputMessage;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -131,18 +132,7 @@ public class FormHttpMessageWriter extends LoggingCodecSupport
|
||||
Assert.notNull(charset, "No charset"); // should never occur
|
||||
|
||||
return Mono.from(inputStream).flatMap(form -> {
|
||||
if (logger.isDebugEnabled()) {
|
||||
String s = Hints.getLogPrefix(hints) + "Writing " +
|
||||
(isEnableLoggingRequestDetails() ?
|
||||
formatValue(form, logger.isTraceEnabled()) :
|
||||
"form fields " + form.keySet() + " (content masked)");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
}
|
||||
logFormData(form, hints);
|
||||
String value = serializeForm(form, charset);
|
||||
ByteBuffer byteBuffer = charset.encode(value);
|
||||
DataBuffer buffer = message.bufferFactory().wrap(byteBuffer);
|
||||
@@ -163,6 +153,13 @@ public class FormHttpMessageWriter extends LoggingCodecSupport
|
||||
}
|
||||
}
|
||||
|
||||
private void logFormData(MultiValueMap<String, String> form, Map<String, Object> hints) {
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Writing " +
|
||||
(isEnableLoggingRequestDetails() ?
|
||||
LogFormatUtils.formatValue(form, !traceOn) :
|
||||
"form fields " + form.keySet() + " (content masked)"));
|
||||
}
|
||||
|
||||
protected String serializeForm(MultiValueMap<String, String> formData, Charset charset) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
formData.forEach((name, values) ->
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.http.codec;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.http.HttpLogging;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Base class for {@link org.springframework.core.codec.Encoder},
|
||||
@@ -56,20 +55,4 @@ public class LoggingCodecSupport {
|
||||
return this.enableLoggingRequestDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the given value via {{toString()}}, either in full or truncated
|
||||
* if it has 100 or more characters.
|
||||
* @param value the value to format
|
||||
* @param logFullValue whether to log in full or truncate if necessary
|
||||
* @return the formatted value
|
||||
* @since 5.1
|
||||
*/
|
||||
protected String formatValue(@Nullable Object value, boolean logFullValue) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
String s = value instanceof CharSequence ? "\"" + value + "\"" : value.toString();
|
||||
return logFullValue || s.length() < 100 ? s : s.substring(0, 100) + " (truncated)...";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.springframework.core.codec.CodecException;
|
||||
import org.springframework.core.codec.DecodingException;
|
||||
import org.springframework.core.codec.Hints;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.http.codec.HttpMessageDecoder;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
@@ -115,15 +116,11 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple
|
||||
return tokens.map(tokenBuffer -> {
|
||||
try {
|
||||
Object value = reader.readValue(tokenBuffer.asParser(getObjectMapper()));
|
||||
if (logger.isDebugEnabled() && !Hints.isLoggingSuppressed(hints)) {
|
||||
boolean traceOn = logger.isTraceEnabled();
|
||||
String s = Hints.getLogPrefix(hints) + "Decoded [" + formatValue(value, traceOn) + "]";
|
||||
if (traceOn) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
if (!Hints.isLoggingSuppressed(hints)) {
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> {
|
||||
String formatted = LogFormatUtils.formatValue(value, !traceOn);
|
||||
return Hints.getLogPrefix(hints) + "Decoded [" + formatted + "]";
|
||||
});
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ import org.springframework.core.codec.EncodingException;
|
||||
import org.springframework.core.codec.Hints;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.HttpMessageEncoder;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
@@ -141,15 +142,11 @@ public abstract class AbstractJackson2Encoder extends Jackson2CodecSupport imple
|
||||
private DataBuffer encodeValue(Object value, @Nullable MimeType mimeType, DataBufferFactory bufferFactory,
|
||||
ResolvableType elementType, @Nullable Map<String, Object> hints, JsonEncoding encoding) {
|
||||
|
||||
if (logger.isDebugEnabled() && !Hints.isLoggingSuppressed(hints)) {
|
||||
boolean traceOn = logger.isTraceEnabled();
|
||||
String s = Hints.getLogPrefix(hints) + "Encoding [" + formatValue(value, traceOn) + "]";
|
||||
if (traceOn) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
if (!Hints.isLoggingSuppressed(hints)) {
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> {
|
||||
String formatted = LogFormatUtils.formatValue(value, !traceOn);
|
||||
return Hints.getLogPrefix(hints) + "Encoding [" + formatted + "]";
|
||||
});
|
||||
}
|
||||
|
||||
JavaType javaType = getJavaType(elementType.getType(), null);
|
||||
|
||||
@@ -125,12 +125,4 @@ public abstract class Jackson2CodecSupport {
|
||||
@Nullable
|
||||
protected abstract <A extends Annotation> A getAnnotation(MethodParameter parameter, Class<A> annotType);
|
||||
|
||||
String formatValue(@Nullable Object value, boolean logFullValue) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
String s = value instanceof CharSequence ? "\"" + value + "\"" : value.toString();
|
||||
return logFullValue || s.length() < 100 ? s : s.substring(0, 100) + " (truncated)...";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.Hints;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ReactiveHttpInputMessage;
|
||||
import org.springframework.http.codec.HttpMessageReader;
|
||||
@@ -94,18 +95,10 @@ public class MultipartHttpMessageReader extends LoggingCodecSupport
|
||||
return this.partReader.read(elementType, inputMessage, allHints)
|
||||
.collectMultimap(Part::name)
|
||||
.doOnNext(map -> {
|
||||
if (logger.isDebugEnabled()) {
|
||||
String s = Hints.getLogPrefix(hints) + "Parsed " +
|
||||
(isEnableLoggingRequestDetails() ?
|
||||
formatValue(map, logger.isTraceEnabled()) :
|
||||
"parts " + map.keySet() + " (content masked)");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
}
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Parsed " +
|
||||
(isEnableLoggingRequestDetails() ?
|
||||
LogFormatUtils.formatValue(map, !traceOn) :
|
||||
"parts " + map.keySet() + " (content masked)"));
|
||||
})
|
||||
.map(this::toMultiValueMap);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -225,18 +226,10 @@ public class MultipartHttpMessageWriter extends LoggingCodecSupport
|
||||
|
||||
outputMessage.getHeaders().setContentType(new MediaType(MediaType.MULTIPART_FORM_DATA, params));
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
String s = Hints.getLogPrefix(hints) + "Encoding " +
|
||||
(isEnableLoggingRequestDetails() ?
|
||||
formatValue(map, logger.isTraceEnabled()) :
|
||||
"parts " + map.keySet() + " (content masked)");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
}
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Encoding " +
|
||||
(isEnableLoggingRequestDetails() ?
|
||||
LogFormatUtils.formatValue(map, !traceOn) :
|
||||
"parts " + map.keySet() + " (content masked)"));
|
||||
|
||||
Flux<DataBuffer> body = Flux.fromIterable(map.entrySet())
|
||||
.concatMap(entry -> encodePartValues(boundary, entry.getKey(), entry.getValue()))
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ReactiveHttpInputMessage;
|
||||
@@ -95,17 +96,11 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem
|
||||
public Flux<Part> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints) {
|
||||
return Flux.create(new SynchronossPartGenerator(message, this.bufferFactory, this.streamStorageFactory))
|
||||
.doOnNext(part -> {
|
||||
if (logger.isDebugEnabled() && !Hints.isLoggingSuppressed(hints)) {
|
||||
String s = Hints.getLogPrefix(hints) + "Parsed " +
|
||||
if (!Hints.isLoggingSuppressed(hints)) {
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Parsed " +
|
||||
(isEnableLoggingRequestDetails() ?
|
||||
formatValue(part, logger.isTraceEnabled()) :
|
||||
"parts '" + part.name() + "' (content masked)");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
LogFormatUtils.formatValue(part, !traceOn) :
|
||||
"parts '" + part.name() + "' (content masked)"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.springframework.core.codec.CodecException;
|
||||
import org.springframework.core.codec.DecodingException;
|
||||
import org.springframework.core.codec.Hints;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -107,16 +108,10 @@ public class Jaxb2XmlDecoder extends AbstractDecoder<Object> {
|
||||
|
||||
return splitEvents.map(events -> {
|
||||
Object value = unmarshal(events, outputClass);
|
||||
if (logger.isDebugEnabled()) {
|
||||
boolean traceOn = logger.isTraceEnabled();
|
||||
String s = Hints.getLogPrefix(hints) + "Decoded [" + formatValue(value, traceOn) + "]";
|
||||
if (traceOn) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
}
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> {
|
||||
String formatted = LogFormatUtils.formatValue(value, !traceOn);
|
||||
return Hints.getLogPrefix(hints) + "Decoded [" + formatted + "]";
|
||||
});
|
||||
return value;
|
||||
});
|
||||
}
|
||||
@@ -213,14 +208,6 @@ public class Jaxb2XmlDecoder extends AbstractDecoder<Object> {
|
||||
return xmlEventFlux.flatMap(new SplitFunction(desiredName));
|
||||
}
|
||||
|
||||
String formatValue(@Nullable Object value, boolean logFullValue) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
String s = value instanceof CharSequence ? "\"" + value + "\"" : value.toString();
|
||||
return logFullValue || s.length() < 100 ? s : s.substring(0, 100) + " (truncated)...";
|
||||
}
|
||||
|
||||
|
||||
private static class SplitFunction implements Function<XMLEvent, Publisher<? extends List<XMLEvent>>> {
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.springframework.core.codec.EncodingException;
|
||||
import org.springframework.core.codec.Hints;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.MimeType;
|
||||
@@ -78,15 +79,11 @@ public class Jaxb2XmlEncoder extends AbstractSingleValueEncoder<Object> {
|
||||
protected Flux<DataBuffer> encode(Object value, DataBufferFactory dataBufferFactory,
|
||||
ResolvableType type, @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
try {
|
||||
if (logger.isDebugEnabled() && !Hints.isLoggingSuppressed(hints)) {
|
||||
boolean traceOn = logger.isTraceEnabled();
|
||||
String s = Hints.getLogPrefix(hints) + "Encoding [" + formatValue(value, traceOn) + "]";
|
||||
if (traceOn) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
if (!Hints.isLoggingSuppressed(hints)) {
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> {
|
||||
String formatted = LogFormatUtils.formatValue(value, !traceOn);
|
||||
return Hints.getLogPrefix(hints) + "Encoding [" + formatted + "]";
|
||||
});
|
||||
}
|
||||
DataBuffer buffer = dataBufferFactory.allocateBuffer(1024);
|
||||
OutputStream outputStream = buffer.asOutputStream();
|
||||
@@ -104,12 +101,4 @@ public class Jaxb2XmlEncoder extends AbstractSingleValueEncoder<Object> {
|
||||
}
|
||||
}
|
||||
|
||||
String formatValue(@Nullable Object value, boolean logFullValue) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
String s = value instanceof CharSequence ? "\"" + value + "\"" : value.toString();
|
||||
return logFullValue || s.length() < 100 ? s : s.substring(0, 100) + " (truncated)...";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@ public abstract class AbstractListenerWriteFlushProcessor<T> implements Processo
|
||||
* @see AbstractListenerWriteProcessor#rsWriteLogger
|
||||
* @see WriteResultPublisher#rsWriteResultLogger
|
||||
*/
|
||||
protected static final Log rsWriteFlushLogger = LogDelegateFactory.getHiddenLog(AbstractListenerWriteFlushProcessor.class);
|
||||
protected static final Log rsWriteFlushLogger =
|
||||
LogDelegateFactory.getHiddenLog(AbstractListenerWriteFlushProcessor.class);
|
||||
|
||||
|
||||
private final AtomicReference<State> state = new AtomicReference<>(State.UNSUBSCRIBED);
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
@@ -281,16 +282,11 @@ public abstract class CommonsFileUploadSupport {
|
||||
// multipart file field
|
||||
CommonsMultipartFile file = createMultipartFile(fileItem);
|
||||
multipartFiles.add(file.getName(), file);
|
||||
if (logger.isDebugEnabled()) {
|
||||
String message = "Part '" + file.getName() + "', " +
|
||||
"size " + file.getSize() + " bytes, filename='" + file.getOriginalFilename() + "'";
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(message + ", storage=" + file.getStorageDescription());
|
||||
}
|
||||
else {
|
||||
logger.debug(message);
|
||||
}
|
||||
}
|
||||
LogFormatUtils.traceDebug(logger, traceOn ->
|
||||
"Part '" + file.getName() + "', size " + file.getSize() +
|
||||
" bytes, filename='" + file.getOriginalFilename() + "'" +
|
||||
(traceOn ? ", storage=" + file.getStorageDescription() : "")
|
||||
);
|
||||
}
|
||||
}
|
||||
return new MultipartParsingResult(multipartFiles, multipartParameters, multipartParameterContentTypes);
|
||||
@@ -323,16 +319,10 @@ public abstract class CommonsFileUploadSupport {
|
||||
if (file instanceof CommonsMultipartFile) {
|
||||
CommonsMultipartFile cmf = (CommonsMultipartFile) file;
|
||||
cmf.getFileItem().delete();
|
||||
if (logger.isDebugEnabled()) {
|
||||
String filename = cmf.getOriginalFilename();
|
||||
String message = "Cleaning up part '" + cmf.getName() + "', filename '" + filename + "'";
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(message + ", stored " + cmf.getStorageDescription());
|
||||
}
|
||||
else {
|
||||
logger.debug(message);
|
||||
}
|
||||
}
|
||||
LogFormatUtils.traceDebug(logger, traceOn ->
|
||||
"Cleaning up part '" + cmf.getName() +
|
||||
"', filename '" + cmf.getOriginalFilename() + "'" +
|
||||
(traceOn ? ", stored " + cmf.getStorageDescription() : ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.apache.commons.fileupload.disk.DiskFileItem;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@@ -165,20 +166,15 @@ public class CommonsMultipartFile implements MultipartFile, Serializable {
|
||||
|
||||
try {
|
||||
this.fileItem.write(dest);
|
||||
if (logger.isDebugEnabled()) {
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> {
|
||||
String action = "transferred";
|
||||
if (!this.fileItem.isInMemory()) {
|
||||
action = (isAvailable() ? "copied" : "moved");
|
||||
}
|
||||
String message = "Part '" + getName() + "', filename '" + getOriginalFilename() + "'";
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(message + ", stored " + getStorageDescription() + ": " + action +
|
||||
" to [" + dest.getAbsolutePath() + "]");
|
||||
}
|
||||
else {
|
||||
logger.debug(message + ": " + action + " to [" + dest.getAbsolutePath() + "]");
|
||||
}
|
||||
}
|
||||
return "Part '" + getName() + "', filename '" + getOriginalFilename() + "'" +
|
||||
(traceOn ? ", stored " + getStorageDescription() : "") +
|
||||
": " + action + " to [" + dest.getAbsolutePath() + "]";
|
||||
});
|
||||
}
|
||||
catch (FileUploadException ex) {
|
||||
throw new IllegalStateException(ex.getMessage(), ex);
|
||||
|
||||
@@ -26,6 +26,7 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.NestedExceptionUtils;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.codec.LoggingCodecSupport;
|
||||
@@ -237,7 +238,10 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
|
||||
}
|
||||
|
||||
ServerWebExchange exchange = createExchange(request, response);
|
||||
logExchange(exchange);
|
||||
|
||||
LogFormatUtils.traceDebug(logger, traceOn ->
|
||||
exchange.getLogPrefix() + formatRequest(exchange.getRequest()) +
|
||||
(traceOn ? ", headers=" + formatHeaders(exchange.getRequest().getHeaders()) : ""));
|
||||
|
||||
return getDelegate().handle(exchange)
|
||||
.doOnSuccess(aVoid -> logResponse(exchange))
|
||||
@@ -250,19 +254,6 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
|
||||
getCodecConfigurer(), getLocaleContextResolver(), this.applicationContext);
|
||||
}
|
||||
|
||||
private void logExchange(ServerWebExchange exchange) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
String logPrefix = exchange.getLogPrefix();
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(logPrefix + formatRequest(request) + ", headers=" + formatHeaders(request.getHeaders()));
|
||||
}
|
||||
else {
|
||||
logger.debug(logPrefix + formatRequest(request));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String formatRequest(ServerHttpRequest request) {
|
||||
String rawQuery = request.getURI().getRawQuery();
|
||||
String query = StringUtils.hasText(rawQuery) ? "?" + rawQuery : "";
|
||||
@@ -270,18 +261,11 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
|
||||
}
|
||||
|
||||
private void logResponse(ServerWebExchange exchange) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
String logPrefix = exchange.getLogPrefix();
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
HttpStatus status = response.getStatusCode();
|
||||
String message = "Completed " + (status != null ? status : "200 OK");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(logPrefix + message + ", headers=" + formatHeaders(response.getHeaders()));
|
||||
}
|
||||
else {
|
||||
logger.debug(logPrefix + message);
|
||||
}
|
||||
}
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> {
|
||||
HttpStatus status = exchange.getResponse().getStatusCode();
|
||||
return exchange.getLogPrefix() + "Completed " + (status != null ? status : "200 OK") +
|
||||
(traceOn ? ", headers=" + formatHeaders(exchange.getResponse().getHeaders()) : "");
|
||||
});
|
||||
}
|
||||
|
||||
private String formatHeaders(HttpHeaders responseHeaders) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -109,29 +110,19 @@ public abstract class ExchangeFunctions {
|
||||
}
|
||||
|
||||
private void logRequest(ClientRequest request) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
String message = request.logPrefix() + "HTTP " + request.method() + " " + request.url();
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(message + ", headers=" + formatHeaders(request.headers()));
|
||||
}
|
||||
else {
|
||||
logger.debug(message);
|
||||
}
|
||||
}
|
||||
LogFormatUtils.traceDebug(logger, traceOn ->
|
||||
request.logPrefix() + "HTTP " + request.method() + " " + request.url() +
|
||||
(traceOn ? ", headers=" + formatHeaders(request.headers()) : "")
|
||||
);
|
||||
}
|
||||
|
||||
private void logResponse(ClientHttpResponse response, String logPrefix) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> {
|
||||
int code = response.getRawStatusCode();
|
||||
HttpStatus status = HttpStatus.resolve(code);
|
||||
String message = logPrefix + "Response " + (status != null ? status : code);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(message + ", headers=" + formatHeaders(response.getHeaders()));
|
||||
}
|
||||
else {
|
||||
logger.debug(message);
|
||||
}
|
||||
}
|
||||
return logPrefix + "Response " + (status != null ? status : code) +
|
||||
(traceOn ? ", headers=" + formatHeaders(response.getHeaders()) : "");
|
||||
});
|
||||
}
|
||||
|
||||
private String formatHeaders(HttpHeaders headers) {
|
||||
|
||||
@@ -48,6 +48,7 @@ import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.ui.context.ThemeSource;
|
||||
@@ -951,7 +952,7 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
}
|
||||
|
||||
private void logRequest(HttpServletRequest request) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> {
|
||||
String params;
|
||||
if (isEnableLoggingRequestDetails()) {
|
||||
params = request.getParameterMap().entrySet().stream()
|
||||
@@ -968,19 +969,19 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
String message = (dispatchType + request.getMethod() + " \"" + getRequestUri(request) +
|
||||
query + "\", parameters={" + params + "}");
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
if (traceOn) {
|
||||
List<String> values = Collections.list(request.getHeaderNames());
|
||||
String headers = values.size() > 0 ? "masked" : "";
|
||||
if (isEnableLoggingRequestDetails()) {
|
||||
headers = values.stream().map(name -> name + ":" + Collections.list(request.getHeaders(name)))
|
||||
.collect(Collectors.joining(", "));
|
||||
}
|
||||
logger.trace(message + ", headers={" + headers + "} in DispatcherServlet '" + getServletName() + "'");
|
||||
return message + ", headers={" + headers + "} in DispatcherServlet '" + getServletName() + "'";
|
||||
}
|
||||
else {
|
||||
logger.debug(message);
|
||||
return message;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1082,7 +1082,9 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
||||
if (failureCause != null) {
|
||||
if (!initialDispatch) {
|
||||
// FORWARD/ERROR/ASYNC: minimal message (there should be enough context already)
|
||||
logger.debug("Unresolved failure from \"" + dispatchType + "\" dispatch: " + failureCause);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Unresolved failure from \"" + dispatchType + "\" dispatch: " + failureCause);
|
||||
}
|
||||
}
|
||||
else if (logger.isTraceEnabled()) {
|
||||
logger.trace("Failed to complete request", failureCause);
|
||||
|
||||
@@ -37,6 +37,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpInputMessage;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -223,17 +224,12 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
|
||||
throw new HttpMediaTypeNotSupportedException(contentType, this.allSupportedMediaTypes);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
boolean traceOn = logger.isTraceEnabled();
|
||||
String s = "Read \"" + contentType + "\" to [" +
|
||||
RequestMappingHandlerAdapter.formatValue(body, traceOn) + "]";
|
||||
if (traceOn) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
}
|
||||
MediaType selectedContentType = contentType;
|
||||
Object theBody = body;
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> {
|
||||
String formatted = LogFormatUtils.formatValue(theBody, !traceOn);
|
||||
return "Read \"" + selectedContentType + "\" to [" + formatted + "]";
|
||||
});
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.ResourceRegion;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpOutputMessage;
|
||||
@@ -280,16 +281,9 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||
(Class<? extends HttpMessageConverter<?>>) converter.getClass(),
|
||||
inputMessage, outputMessage);
|
||||
if (body != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
boolean traceOn = logger.isTraceEnabled();
|
||||
String s = "Writing [" + RequestMappingHandlerAdapter.formatValue(body, traceOn) + "]";
|
||||
if (traceOn) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
}
|
||||
Object theBody = body;
|
||||
LogFormatUtils.traceDebug(logger, traceOn ->
|
||||
"Writing [" + LogFormatUtils.formatValue(theBody, traceOn) + "]");
|
||||
addContentDispositionHeader(inputMessage, outputMessage);
|
||||
if (genericConverter != null) {
|
||||
genericConverter.write(body, targetType, selectedMediaType, outputMessage);
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.log.LogFormatUtils;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||
@@ -884,15 +885,10 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
Object result = asyncManager.getConcurrentResult();
|
||||
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
|
||||
asyncManager.clearConcurrentResult();
|
||||
if (logger.isDebugEnabled()) {
|
||||
String s = "Resume with async result [" + formatValue(result, logger.isTraceEnabled()) + "]";
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(s);
|
||||
}
|
||||
else {
|
||||
logger.debug(s);
|
||||
}
|
||||
}
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> {
|
||||
String formatted = LogFormatUtils.formatValue(result, !traceOn);
|
||||
return "Resume with async result [" + formatted + "]";
|
||||
});
|
||||
invocableMethod = invocableMethod.wrapConcurrentResult(result);
|
||||
}
|
||||
|
||||
@@ -1024,12 +1020,4 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
return mav;
|
||||
}
|
||||
|
||||
static String formatValue(@Nullable Object body, boolean logFullBody) {
|
||||
if (body == null) {
|
||||
return "";
|
||||
}
|
||||
String s = body instanceof CharSequence ? "\"" + body + "\"" : body.toString();
|
||||
return logFullBody || s.length() < 100 ? s : s.substring(0, 100) + " (truncated)...";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user