Correlate data buffers to request log messages
HttpMessageWriter implementations now attach the request log prefix as a hint to created data buffers when the logger associated with the writer is at DEBUG level. Closes gh-26230
This commit is contained in:
@@ -21,6 +21,8 @@ import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@@ -148,4 +150,22 @@ public abstract class Hints {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the hints contain a {@link #LOG_PREFIX_HINT} and the given logger has
|
||||
* DEBUG level enabled, apply the log prefix as a hint to the given buffer
|
||||
* via {@link DataBufferUtils#touch(DataBuffer, Object)}.
|
||||
* @param buffer the buffer to touch
|
||||
* @param hints the hints map to check for a log prefix
|
||||
* @param logger the logger whose level to check
|
||||
* @since 5.3.2
|
||||
*/
|
||||
public static void touchDataBuffer(DataBuffer buffer, @Nullable Map<String, Object> hints, Log logger) {
|
||||
if (logger.isDebugEnabled() && hints != null) {
|
||||
Object logPrefix = hints.get(LOG_PREFIX_HINT);
|
||||
if (logPrefix != null) {
|
||||
DataBufferUtils.touch(buffer, logPrefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -130,6 +130,9 @@ public class ResourceRegionEncoder extends AbstractEncoder<ResourceRegion> {
|
||||
}
|
||||
|
||||
Flux<DataBuffer> in = DataBufferUtils.read(resource, position, bufferFactory, this.bufferSize);
|
||||
if (logger.isDebugEnabled()) {
|
||||
in = in.doOnNext(buffer -> Hints.touchDataBuffer(buffer, hints, logger));
|
||||
}
|
||||
return DataBufferUtils.takeUntilByteCount(in, count);
|
||||
}
|
||||
|
||||
|
||||
@@ -487,6 +487,24 @@ public abstract class DataBufferUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate the given hint with the data buffer if it is a pooled buffer
|
||||
* and supports leak tracking.
|
||||
* @param dataBuffer the data buffer to attach the hint to
|
||||
* @param hint the hint to attach
|
||||
* @return the input buffer
|
||||
* @since 5.3.2
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends DataBuffer> T touch(T dataBuffer, Object hint) {
|
||||
if (dataBuffer instanceof PooledDataBuffer) {
|
||||
return (T) ((PooledDataBuffer) dataBuffer).touch(hint);
|
||||
}
|
||||
else {
|
||||
return dataBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the given data buffer, if it is a {@link PooledDataBuffer} and
|
||||
* has been {@linkplain PooledDataBuffer#isAllocated() allocated}.
|
||||
|
||||
@@ -315,6 +315,12 @@ public class NettyDataBuffer implements PooledDataBuffer {
|
||||
return new NettyDataBuffer(this.byteBuf.retain(), this.dataBufferFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PooledDataBuffer touch(Object hint) {
|
||||
this.byteBuf.touch(hint);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean release() {
|
||||
return this.byteBuf.release();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -38,6 +38,13 @@ public interface PooledDataBuffer extends DataBuffer {
|
||||
*/
|
||||
PooledDataBuffer retain();
|
||||
|
||||
/**
|
||||
* Associate the given hint with the data buffer for debugging purposes.
|
||||
* @return this buffer
|
||||
* @since 5.3.2
|
||||
*/
|
||||
PooledDataBuffer touch(Object hint);
|
||||
|
||||
/**
|
||||
* Decrease the reference count for this buffer by one,
|
||||
* and deallocate it once the count reaches zero.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.core.testfixture.io.buffer;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DataBufferWrapper;
|
||||
import org.springframework.core.io.buffer.PooledDataBuffer;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -67,19 +68,19 @@ class LeakAwareDataBuffer extends DataBufferWrapper implements PooledDataBuffer
|
||||
|
||||
@Override
|
||||
public PooledDataBuffer retain() {
|
||||
DataBuffer delegate = dataBuffer();
|
||||
if (delegate instanceof PooledDataBuffer) {
|
||||
((PooledDataBuffer) delegate).retain();
|
||||
}
|
||||
DataBufferUtils.retain(dataBuffer());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PooledDataBuffer touch(Object hint) {
|
||||
DataBufferUtils.touch(dataBuffer(), hint);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean release() {
|
||||
DataBuffer delegate = dataBuffer();
|
||||
if (delegate instanceof PooledDataBuffer) {
|
||||
((PooledDataBuffer) delegate).release();
|
||||
}
|
||||
DataBufferUtils.release(dataBuffer());
|
||||
return isAllocated();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user