Merge pull request #5789 from eclipse/jetty-9.4.x-5783-ConnectionStatisticsRates

Fix the calculation of rates in ConnectionStatistics
This commit is contained in:
Lachlan 2020-12-28 16:26:55 +11:00 committed by GitHub
commit 3d11d4e071
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 94 additions and 37 deletions

View File

@ -19,8 +19,6 @@
package org.eclipse.jetty.io; package org.eclipse.jetty.io;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder; import java.util.concurrent.atomic.LongAdder;
import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedAttribute;
@ -29,6 +27,7 @@ import org.eclipse.jetty.util.annotation.ManagedOperation;
import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.statistic.CounterStatistic; import org.eclipse.jetty.util.statistic.CounterStatistic;
import org.eclipse.jetty.util.statistic.RateCounter;
import org.eclipse.jetty.util.statistic.SampleStatistic; import org.eclipse.jetty.util.statistic.SampleStatistic;
/** /**
@ -43,28 +42,29 @@ public class ConnectionStatistics extends AbstractLifeCycle implements Connectio
{ {
private final CounterStatistic _connections = new CounterStatistic(); private final CounterStatistic _connections = new CounterStatistic();
private final SampleStatistic _connectionsDuration = new SampleStatistic(); private final SampleStatistic _connectionsDuration = new SampleStatistic();
private final LongAdder _rcvdBytes = new LongAdder();
private final AtomicLong _bytesInStamp = new AtomicLong(); private final LongAdder _bytesIn = new LongAdder();
private final LongAdder _sentBytes = new LongAdder(); private final LongAdder _bytesOut = new LongAdder();
private final AtomicLong _bytesOutStamp = new AtomicLong();
private final LongAdder _messagesIn = new LongAdder(); private final LongAdder _messagesIn = new LongAdder();
private final AtomicLong _messagesInStamp = new AtomicLong();
private final LongAdder _messagesOut = new LongAdder(); private final LongAdder _messagesOut = new LongAdder();
private final AtomicLong _messagesOutStamp = new AtomicLong(); private final RateCounter _bytesInRate = new RateCounter();
private final RateCounter _bytesOutRate = new RateCounter();
private final RateCounter _messagesInRate = new RateCounter();
private final RateCounter _messagesOutRate = new RateCounter();
@ManagedOperation(value = "Resets the statistics", impact = "ACTION") @ManagedOperation(value = "Resets the statistics", impact = "ACTION")
public void reset() public void reset()
{ {
_connections.reset(); _connections.reset();
_connectionsDuration.reset(); _connectionsDuration.reset();
_rcvdBytes.reset(); _bytesIn.reset();
_bytesInStamp.set(System.nanoTime()); _bytesOut.reset();
_sentBytes.reset();
_bytesOutStamp.set(System.nanoTime());
_messagesIn.reset(); _messagesIn.reset();
_messagesInStamp.set(System.nanoTime());
_messagesOut.reset(); _messagesOut.reset();
_messagesOutStamp.set(System.nanoTime()); _bytesInRate.reset();
_bytesOutRate.reset();
_messagesInRate.reset();
_messagesOutRate.reset();
} }
@Override @Override
@ -89,53 +89,63 @@ public class ConnectionStatistics extends AbstractLifeCycle implements Connectio
return; return;
_connections.decrement(); _connections.decrement();
_connectionsDuration.record(System.currentTimeMillis() - connection.getCreatedTimeStamp());
long elapsed = System.currentTimeMillis() - connection.getCreatedTimeStamp();
_connectionsDuration.record(elapsed);
long bytesIn = connection.getBytesIn(); long bytesIn = connection.getBytesIn();
if (bytesIn > 0) if (bytesIn > 0)
_rcvdBytes.add(bytesIn); {
_bytesIn.add(bytesIn);
_bytesInRate.add(bytesIn);
}
long bytesOut = connection.getBytesOut(); long bytesOut = connection.getBytesOut();
if (bytesOut > 0) if (bytesOut > 0)
_sentBytes.add(bytesOut); {
_bytesOut.add(bytesOut);
_bytesOutRate.add(bytesOut);
}
long messagesIn = connection.getMessagesIn(); long messagesIn = connection.getMessagesIn();
if (messagesIn > 0) if (messagesIn > 0)
{
_messagesIn.add(messagesIn); _messagesIn.add(messagesIn);
_messagesInRate.add(messagesIn);
}
long messagesOut = connection.getMessagesOut(); long messagesOut = connection.getMessagesOut();
if (messagesOut > 0) if (messagesOut > 0)
{
_messagesOut.add(messagesOut); _messagesOut.add(messagesOut);
_messagesOutRate.add(messagesOut);
}
} }
@ManagedAttribute("Total number of bytes received by tracked connections") @ManagedAttribute("Total number of bytes received by tracked connections")
public long getReceivedBytes() public long getReceivedBytes()
{ {
return _rcvdBytes.sum(); return _bytesIn.sum();
} }
@ManagedAttribute("Total number of bytes received per second since the last invocation of this method") @ManagedAttribute("Total number of bytes received per second since the last invocation of this method")
public long getReceivedBytesRate() public long getReceivedBytesRate()
{ {
long now = System.nanoTime(); long rate = _bytesInRate.getRate();
long then = _bytesInStamp.getAndSet(now); _bytesInRate.reset();
long elapsed = TimeUnit.NANOSECONDS.toMillis(now - then); return rate;
return elapsed == 0 ? 0 : getReceivedBytes() * 1000 / elapsed;
} }
@ManagedAttribute("Total number of bytes sent by tracked connections") @ManagedAttribute("Total number of bytes sent by tracked connections")
public long getSentBytes() public long getSentBytes()
{ {
return _sentBytes.sum(); return _bytesOut.sum();
} }
@ManagedAttribute("Total number of bytes sent per second since the last invocation of this method") @ManagedAttribute("Total number of bytes sent per second since the last invocation of this method")
public long getSentBytesRate() public long getSentBytesRate()
{ {
long now = System.nanoTime(); long rate = _bytesOutRate.getRate();
long then = _bytesOutStamp.getAndSet(now); _bytesOutRate.reset();
long elapsed = TimeUnit.NANOSECONDS.toMillis(now - then); return rate;
return elapsed == 0 ? 0 : getSentBytes() * 1000 / elapsed;
} }
@ManagedAttribute("The max duration of a connection in ms") @ManagedAttribute("The max duration of a connection in ms")
@ -183,10 +193,9 @@ public class ConnectionStatistics extends AbstractLifeCycle implements Connectio
@ManagedAttribute("Total number of messages received per second since the last invocation of this method") @ManagedAttribute("Total number of messages received per second since the last invocation of this method")
public long getReceivedMessagesRate() public long getReceivedMessagesRate()
{ {
long now = System.nanoTime(); long rate = _messagesInRate.getRate();
long then = _messagesInStamp.getAndSet(now); _messagesInRate.reset();
long elapsed = TimeUnit.NANOSECONDS.toMillis(now - then); return rate;
return elapsed == 0 ? 0 : getReceivedMessages() * 1000 / elapsed;
} }
@ManagedAttribute("The total number of messages sent") @ManagedAttribute("The total number of messages sent")
@ -198,10 +207,9 @@ public class ConnectionStatistics extends AbstractLifeCycle implements Connectio
@ManagedAttribute("Total number of messages sent per second since the last invocation of this method") @ManagedAttribute("Total number of messages sent per second since the last invocation of this method")
public long getSentMessagesRate() public long getSentMessagesRate()
{ {
long now = System.nanoTime(); long rate = _messagesOutRate.getRate();
long then = _messagesOutStamp.getAndSet(now); _messagesOutRate.reset();
long elapsed = TimeUnit.NANOSECONDS.toMillis(now - then); return rate;
return elapsed == 0 ? 0 : getSentMessages() * 1000 / elapsed;
} }
@Override @Override

View File

@ -0,0 +1,49 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.util.statistic;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
/**
* Counts the rate that {@link Long}s are added to this from the time of creation or the last call to {@link #reset()}.
*/
public class RateCounter
{
private final LongAdder _total = new LongAdder();
private final AtomicLong _timeStamp = new AtomicLong(System.nanoTime());
public void add(long l)
{
_total.add(l);
}
public long getRate()
{
long elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - _timeStamp.get());
return elapsed == 0 ? 0 : _total.sum() * 1000 / elapsed;
}
public void reset()
{
_timeStamp.getAndSet(System.nanoTime());
_total.reset();
}
}