484818 - Expose interesting HTTP/2 attributes and operations via JMX.

Added flow control stall times and improved dump().
This commit is contained in:
Simone Bordet 2015-12-28 14:30:24 +01:00
parent 997b868ecd
commit fdadc942e9
3 changed files with 52 additions and 9 deletions

View File

@ -18,6 +18,10 @@
package org.eclipse.jetty.http2; package org.eclipse.jetty.http2;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.jetty.http2.api.Stream; import org.eclipse.jetty.http2.api.Stream;
@ -25,15 +29,20 @@ import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.ManagedOperation; import org.eclipse.jetty.util.annotation.ManagedOperation;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
@ManagedObject @ManagedObject
public abstract class AbstractFlowControlStrategy implements FlowControlStrategy public abstract class AbstractFlowControlStrategy implements FlowControlStrategy, Dumpable
{ {
protected static final Logger LOG = Log.getLogger(FlowControlStrategy.class); protected static final Logger LOG = Log.getLogger(FlowControlStrategy.class);
private final AtomicLong sessionStalls = new AtomicLong(); private final AtomicLong sessionStall = new AtomicLong();
private final AtomicLong sessionStallTime = new AtomicLong();
private final Map<IStream, Long> streamsStalls = new ConcurrentHashMap<>();
private final AtomicLong streamsStallTime = new AtomicLong();
private int initialStreamSendWindow; private int initialStreamSendWindow;
private int initialStreamRecvWindow; private int initialStreamRecvWindow;
@ -174,38 +183,62 @@ public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
protected void onSessionStalled(ISession session) protected void onSessionStalled(ISession session)
{ {
sessionStall.set(System.nanoTime());
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Session stalled {}", session); LOG.debug("Session stalled {}", session);
sessionStalls.incrementAndGet();
} }
protected void onStreamStalled(IStream stream) protected void onStreamStalled(IStream stream)
{ {
streamsStalls.put(stream, System.nanoTime());
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Stream stalled {}", stream); LOG.debug("Stream stalled {}", stream);
} }
protected void onSessionUnstalled(ISession session) protected void onSessionUnstalled(ISession session)
{ {
sessionStallTime.addAndGet(System.nanoTime() - sessionStall.getAndSet(0));
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Session unstalled {}", session); LOG.debug("Session unstalled {}", session);
} }
protected void onStreamUnstalled(IStream stream) protected void onStreamUnstalled(IStream stream)
{ {
Long time = streamsStalls.remove(stream);
if (time != null)
streamsStallTime.addAndGet(System.nanoTime() - time);
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Stream unstalled {}", stream); LOG.debug("Stream unstalled {}", stream);
} }
@ManagedAttribute(value = "The number of times the session flow control has stalled", readonly = true) @ManagedAttribute(value = "The time, in milliseconds, that the session flow control has stalled", readonly = true)
public long getSessionStallCount() public long getSessionStallTime()
{ {
return sessionStalls.get(); return TimeUnit.NANOSECONDS.toMillis(sessionStallTime.get());
}
@ManagedAttribute(value = "The time, in milliseconds, that the streams flow control has stalled", readonly = true)
public long getStreamsStallTime()
{
return TimeUnit.NANOSECONDS.toMillis(streamsStallTime.get());
} }
@ManagedOperation(value = "Resets the statistics", impact = "ACTION") @ManagedOperation(value = "Resets the statistics", impact = "ACTION")
public void reset() public void reset()
{ {
sessionStalls.set(0); sessionStallTime.set(0);
streamsStallTime.set(0);
}
@Override
public String dump()
{
return ContainerLifeCycle.dump(this);
}
@Override
public void dump(Appendable out, String indent) throws IOException
{
out.append(toString()).append(System.lineSeparator());
} }
} }

View File

@ -198,4 +198,15 @@ public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy
Atomics.updateMax(maxSessionRecvWindow, sessionWindow); Atomics.updateMax(maxSessionRecvWindow, sessionWindow);
} }
} }
@Override
public String toString()
{
return String.format("%s@%x[ratio=%.2f,sessionStallTime=%dms,streamsStallTime=%dms]",
getClass().getSimpleName(),
hashCode(),
bufferRatio,
getSessionStallTime(),
getStreamsStallTime());
}
} }

View File

@ -34,7 +34,6 @@ import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.Name; import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.component.LifeCycle;
@ManagedObject @ManagedObject
@ -159,7 +158,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize()); return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize());
} }
private static class ConnectionListener extends ContainerLifeCycle implements Connection.Listener private class ConnectionListener implements Connection.Listener
{ {
@Override @Override
public void onOpened(Connection connection) public void onOpened(Connection connection)