All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.signalfx.shaded.jetty.io.ConnectionStatistics Maven / Gradle / Ivy

//
//  ========================================================================
//  Copyright (c) 1995-2022 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 com.signalfx.shaded.jetty.io;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.LongAdder;

import com.signalfx.shaded.jetty.util.annotation.ManagedAttribute;
import com.signalfx.shaded.jetty.util.annotation.ManagedObject;
import com.signalfx.shaded.jetty.util.annotation.ManagedOperation;
import com.signalfx.shaded.jetty.util.component.AbstractLifeCycle;
import com.signalfx.shaded.jetty.util.component.Dumpable;
import com.signalfx.shaded.jetty.util.statistic.CounterStatistic;
import com.signalfx.shaded.jetty.util.statistic.RateCounter;
import com.signalfx.shaded.jetty.util.statistic.SampleStatistic;

/**
 * 

A {@link Connection.Listener} that tracks connection statistics.

*

Adding an instance of this class as a bean to a ServerConnector * or ConnectionFactory (for the server) or to HttpClient (for the client) * will trigger the tracking of the connection statistics for all * connections managed by the server or by the client.

*

The statistics for a connection are gathered when the connection * is closed.

*

ConnectionStatistics instances must be {@link #start() started} * to collect statistics, either as part of starting the whole component * tree, or explicitly if the component tree has already been started.

*/ @ManagedObject("Tracks statistics on connections") public class ConnectionStatistics extends AbstractLifeCycle implements Connection.Listener, Dumpable { private final Stats _stats = new Stats("total"); private final Map _statsMap = new ConcurrentHashMap<>(); @ManagedOperation(value = "Resets the statistics", impact = "ACTION") public void reset() { _stats.reset(); _statsMap.clear(); } @Override protected void doStart() throws Exception { reset(); } @Override public void onOpened(Connection connection) { if (!isStarted()) return; onTotalOpened(connection); onConnectionOpened(connection); } protected void onTotalOpened(Connection connection) { _stats.incrementCount(); } protected void onConnectionOpened(Connection connection) { _statsMap.computeIfAbsent(connection.getClass().getName(), Stats::new).incrementCount(); } @Override public void onClosed(Connection connection) { if (!isStarted()) return; onTotalClosed(connection); onConnectionClosed(connection); } protected void onTotalClosed(Connection connection) { onClosed(_stats, connection); } protected void onConnectionClosed(Connection connection) { Stats stats = _statsMap.get(connection.getClass().getName()); if (stats != null) onClosed(stats, connection); } private void onClosed(Stats stats, Connection connection) { stats.decrementCount(); stats.recordDuration(System.currentTimeMillis() - connection.getCreatedTimeStamp()); long bytesIn = connection.getBytesIn(); if (bytesIn > 0) stats.recordBytesIn(bytesIn); long bytesOut = connection.getBytesOut(); if (bytesOut > 0) stats.recordBytesOut(bytesOut); long messagesIn = connection.getMessagesIn(); if (messagesIn > 0) stats.recordMessagesIn(messagesIn); long messagesOut = connection.getMessagesOut(); if (messagesOut > 0) stats.recordMessagesOut(messagesOut); } @ManagedAttribute("Total number of bytes received by tracked connections") public long getReceivedBytes() { return _stats.getReceivedBytes(); } @ManagedAttribute("Total number of bytes received per second since the last invocation of this method") public long getReceivedBytesRate() { return _stats.getReceivedBytesRate(); } @ManagedAttribute("Total number of bytes sent by tracked connections") public long getSentBytes() { return _stats.getSentBytes(); } @ManagedAttribute("Total number of bytes sent per second since the last invocation of this method") public long getSentBytesRate() { return _stats.getSentBytesRate(); } @ManagedAttribute("The max duration of a connection in ms") public long getConnectionDurationMax() { return _stats.getConnectionDurationMax(); } @ManagedAttribute("The mean duration of a connection in ms") public double getConnectionDurationMean() { return _stats.getConnectionDurationMean(); } @ManagedAttribute("The standard deviation of the duration of a connection") public double getConnectionDurationStdDev() { return _stats.getConnectionDurationStdDev(); } @ManagedAttribute("The total number of connections opened") public long getConnectionsTotal() { return _stats.getConnectionsTotal(); } @ManagedAttribute("The current number of open connections") public long getConnections() { return _stats.getConnections(); } @ManagedAttribute("The max number of open connections") public long getConnectionsMax() { return _stats.getConnectionsMax(); } @ManagedAttribute("The total number of messages received") public long getReceivedMessages() { return _stats.getReceivedMessages(); } @ManagedAttribute("Total number of messages received per second since the last invocation of this method") public long getReceivedMessagesRate() { return _stats.getReceivedMessagesRate(); } @ManagedAttribute("The total number of messages sent") public long getSentMessages() { return _stats.getSentMessages(); } @ManagedAttribute("Total number of messages sent per second since the last invocation of this method") public long getSentMessagesRate() { return _stats.getSentMessagesRate(); } public Map getConnectionStatisticsGroups() { return _statsMap; } @Override public void dump(Appendable out, String indent) throws IOException { List children = new ArrayList<>(); children.add(_stats); children.addAll(_statsMap.values()); Dumpable.dumpObjects(out, indent, this, children.toArray()); } @Override public String toString() { return String.format("%s@%x", getClass().getSimpleName(), hashCode()); } public static class Stats implements Dumpable { private final CounterStatistic _connections = new CounterStatistic(); private final SampleStatistic _connectionsDuration = new SampleStatistic(); private final LongAdder _bytesIn = new LongAdder(); private final RateCounter _bytesInRate = new RateCounter(); private final LongAdder _bytesOut = new LongAdder(); private final RateCounter _bytesOutRate = new RateCounter(); private final LongAdder _messagesIn = new LongAdder(); private final RateCounter _messagesInRate = new RateCounter(); private final LongAdder _messagesOut = new LongAdder(); private final RateCounter _messagesOutRate = new RateCounter(); private final String _name; public Stats(String name) { _name = name; } public void reset() { _connections.reset(); _connectionsDuration.reset(); _bytesIn.reset(); _bytesInRate.reset(); _bytesOut.reset(); _bytesOutRate.reset(); _messagesIn.reset(); _messagesInRate.reset(); _messagesOut.reset(); _messagesOutRate.reset(); } public String getName() { return _name; } public long getReceivedBytes() { return _bytesIn.sum(); } public long getReceivedBytesRate() { long rate = _bytesInRate.getRate(); _bytesInRate.reset(); return rate; } public long getSentBytes() { return _bytesOut.sum(); } public long getSentBytesRate() { long rate = _bytesOutRate.getRate(); _bytesOutRate.reset(); return rate; } public long getConnectionDurationMax() { return _connectionsDuration.getMax(); } public double getConnectionDurationMean() { return _connectionsDuration.getMean(); } public double getConnectionDurationStdDev() { return _connectionsDuration.getStdDev(); } public long getConnectionsTotal() { return _connections.getTotal(); } public long getConnections() { return _connections.getCurrent(); } public long getConnectionsMax() { return _connections.getMax(); } public long getReceivedMessages() { return _messagesIn.sum(); } public long getReceivedMessagesRate() { long rate = _messagesInRate.getRate(); _messagesInRate.reset(); return rate; } public long getSentMessages() { return _messagesOut.sum(); } public long getSentMessagesRate() { long rate = _messagesOutRate.getRate(); _messagesOutRate.reset(); return rate; } public void incrementCount() { _connections.increment(); } public void decrementCount() { _connections.decrement(); } public void recordDuration(long duration) { _connectionsDuration.record(duration); } public void recordBytesIn(long bytesIn) { _bytesIn.add(bytesIn); _bytesInRate.add(bytesIn); } public void recordBytesOut(long bytesOut) { _bytesOut.add(bytesOut); _bytesOutRate.add(bytesOut); } public void recordMessagesIn(long messagesIn) { _messagesIn.add(messagesIn); _messagesInRate.add(messagesIn); } public void recordMessagesOut(long messagesOut) { _messagesOut.add(messagesOut); _messagesOutRate.add(messagesOut); } @Override public void dump(Appendable out, String indent) throws IOException { Dumpable.dumpObjects(out, indent, this, String.format("connections=%s", _connections), String.format("durations=%s", _connectionsDuration), String.format("bytes in/out=%s/%s", getReceivedBytes(), getSentBytes()), String.format("messages in/out=%s/%s", getReceivedMessages(), getSentMessages())); } @Override public String toString() { return String.format("%s[%s]", getClass().getSimpleName(), getName()); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy