|
@@ -34,6 +34,7 @@ import org.elasticsearch.common.lease.Releasables;
|
|
|
import org.elasticsearch.common.network.CloseableChannel;
|
|
|
import org.elasticsearch.common.transport.NetworkExceptionHelper;
|
|
|
import org.elasticsearch.common.transport.TransportAddress;
|
|
|
+import org.elasticsearch.common.unit.TimeValue;
|
|
|
import org.elasticsearch.common.util.BigArrays;
|
|
|
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
|
|
import org.elasticsearch.core.internal.io.IOUtils;
|
|
@@ -50,6 +51,9 @@ final class OutboundHandler {
|
|
|
private final StatsTracker statsTracker;
|
|
|
private final ThreadPool threadPool;
|
|
|
private final BigArrays bigArrays;
|
|
|
+
|
|
|
+ private volatile long slowLogThresholdMs = Long.MAX_VALUE;
|
|
|
+
|
|
|
private volatile TransportMessageListener messageListener = TransportMessageListener.NOOP_LISTENER;
|
|
|
|
|
|
OutboundHandler(String nodeName, Version version, StatsTracker statsTracker, ThreadPool threadPool, BigArrays bigArrays) {
|
|
@@ -60,6 +64,10 @@ final class OutboundHandler {
|
|
|
this.bigArrays = bigArrays;
|
|
|
}
|
|
|
|
|
|
+ void setSlowLogThreshold(TimeValue slowLogThreshold) {
|
|
|
+ this.slowLogThresholdMs = slowLogThreshold.getMillis();
|
|
|
+ }
|
|
|
+
|
|
|
void sendBytes(TcpChannel channel, BytesReference bytes, ActionListener<Void> listener) {
|
|
|
SendContext sendContext = new SendContext(channel, () -> bytes, listener);
|
|
|
try {
|
|
@@ -125,6 +133,7 @@ final class OutboundHandler {
|
|
|
BytesReference reference = sendContext.get();
|
|
|
// stash thread context so that channel event loop is not polluted by thread context
|
|
|
try (ThreadContext.StoredContext existing = threadPool.getThreadContext().stashContext()) {
|
|
|
+ sendContext.startTime = threadPool.relativeTimeInMillis();
|
|
|
channel.sendMessage(reference, sendContext);
|
|
|
} catch (RuntimeException ex) {
|
|
|
sendContext.onFailure(ex);
|
|
@@ -162,6 +171,11 @@ final class OutboundHandler {
|
|
|
public void close() {
|
|
|
IOUtils.closeWhileHandlingException(bytesStreamOutput);
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String toString() {
|
|
|
+ return "MessageSerializer{" + message + "}";
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private class SendContext extends NotifyOnceListener<Void> implements CheckedSupplier<BytesReference, IOException> {
|
|
@@ -171,6 +185,7 @@ final class OutboundHandler {
|
|
|
private final ActionListener<Void> listener;
|
|
|
private final Releasable optionalReleasable;
|
|
|
private long messageSize = -1;
|
|
|
+ private long startTime;
|
|
|
|
|
|
private SendContext(TcpChannel channel, CheckedSupplier<BytesReference, IOException> messageSupplier,
|
|
|
ActionListener<Void> listener) {
|
|
@@ -198,6 +213,15 @@ final class OutboundHandler {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void maybeLogSlowMessage() {
|
|
|
+ final long took = threadPool.relativeTimeInMillis() - startTime;
|
|
|
+ final long logThreshold = slowLogThresholdMs;
|
|
|
+ if (logThreshold > 0 && took > logThreshold) {
|
|
|
+ logger.warn("sending transport message [{}] of size [{}] on [{}] took [{}ms] which is above the warn threshold of [{}ms]",
|
|
|
+ messageSupplier, messageSize, channel, took, logThreshold);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
protected void innerOnResponse(Void v) {
|
|
|
assert messageSize != -1 : "If onResponse is being called, the message should have been serialized";
|
|
@@ -216,7 +240,7 @@ final class OutboundHandler {
|
|
|
}
|
|
|
|
|
|
private void closeAndCallback(Runnable runnable) {
|
|
|
- Releasables.close(optionalReleasable, runnable::run);
|
|
|
+ Releasables.close(optionalReleasable, runnable::run, this::maybeLogSlowMessage);
|
|
|
}
|
|
|
}
|
|
|
}
|