From 2111775cb41de4eed547c04d62605e9ccc0fc5a1 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Wed, 14 Sep 2016 10:19:14 +0200 Subject: [PATCH] Fixes #131 - Improve Connector Statistic names and values. --- .../eclipse/jetty/embedded/LikeJettyXml.java | 4 +- .../embedded/OneServletContextJmxStats.java | 4 +- .../jetty/io/ConnectionStatistics.java | 233 ++++++++++++++++++ .../src/main/config/etc/jetty-stats.xml | 2 +- .../jetty/server/ConnectorStatistics.java | 3 + .../server/ServerConnectionStatistics.java | 34 +++ 6 files changed, 275 insertions(+), 5 deletions(-) create mode 100644 jetty-io/src/main/java/org/eclipse/jetty/io/ConnectionStatistics.java create mode 100644 jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnectionStatistics.java diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java index 328765b559d..ce359c79c81 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java @@ -30,7 +30,6 @@ import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.rewrite.handler.RewriteHandler; import org.eclipse.jetty.security.HashLoginService; -import org.eclipse.jetty.server.ConnectorStatistics; import org.eclipse.jetty.server.DebugListener; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; @@ -39,6 +38,7 @@ import org.eclipse.jetty.server.LowResourceMonitor; import org.eclipse.jetty.server.NCSARequestLog; import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnectionStatistics; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.server.handler.ContextHandlerCollection; @@ -193,7 +193,7 @@ public class LikeJettyXml StatisticsHandler stats = new StatisticsHandler(); stats.setHandler(server.getHandler()); server.setHandler(stats); - ConnectorStatistics.addToAllConnectors(server); + ServerConnectionStatistics.addToAllConnectors(server); // === Rewrite Handler RewriteHandler rewrite = new RewriteHandler(); diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneServletContextJmxStats.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneServletContextJmxStats.java index 80b631d7e99..abc59ca2426 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneServletContextJmxStats.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneServletContextJmxStats.java @@ -21,8 +21,8 @@ package org.eclipse.jetty.embedded; import java.lang.management.ManagementFactory; import org.eclipse.jetty.jmx.MBeanContainer; -import org.eclipse.jetty.server.ConnectorStatistics; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnectionStatistics; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; @@ -44,7 +44,7 @@ public class OneServletContextJmxStats context.addServlet(DefaultServlet.class, "/"); // Add Connector Statistics tracking to all connectors - ConnectorStatistics.addToAllConnectors(server); + ServerConnectionStatistics.addToAllConnectors(server); server.start(); server.join(); diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ConnectionStatistics.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ConnectionStatistics.java new file mode 100644 index 00000000000..42d3fd0f50b --- /dev/null +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ConnectionStatistics.java @@ -0,0 +1,233 @@ +// +// ======================================================================== +// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// 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.io; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.LongAdder; + +import org.eclipse.jetty.util.annotation.ManagedAttribute; +import org.eclipse.jetty.util.annotation.ManagedObject; +import org.eclipse.jetty.util.annotation.ManagedOperation; +import org.eclipse.jetty.util.component.AbstractLifeCycle; +import org.eclipse.jetty.util.component.ContainerLifeCycle; +import org.eclipse.jetty.util.component.Dumpable; +import org.eclipse.jetty.util.statistic.CounterStatistic; +import org.eclipse.jetty.util.statistic.SampleStatistic; + +/** + *

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

+ *

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

+ */ +@ManagedObject("Tracks statistics on connections") +public class ConnectionStatistics extends AbstractLifeCycle implements Connection.Listener, Dumpable +{ + private final CounterStatistic _connections = new CounterStatistic(); + private final SampleStatistic _connectionsDuration = new SampleStatistic(); + private final LongAdder _rcvdBytes = new LongAdder(); + private final AtomicLong _bytesInStamp = new AtomicLong(); + private final LongAdder _sentBytes = new LongAdder(); + private final AtomicLong _bytesOutStamp = new AtomicLong(); + private final LongAdder _messagesIn = new LongAdder(); + private final AtomicLong _messagesInStamp = new AtomicLong(); + private final LongAdder _messagesOut = new LongAdder(); + private final AtomicLong _messagesOutStamp = new AtomicLong(); + + @ManagedOperation(value = "Resets the statistics", impact = "ACTION") + public void reset() + { + _connections.reset(); + _connectionsDuration.reset(); + _rcvdBytes.reset(); + _bytesInStamp.set(System.nanoTime()); + _sentBytes.reset(); + _bytesOutStamp.set(System.nanoTime()); + _messagesIn.reset(); + _messagesInStamp.set(System.nanoTime()); + _messagesOut.reset(); + _messagesOutStamp.set(System.nanoTime()); + } + + @Override + protected void doStart() throws Exception + { + reset(); + } + + @Override + public void onOpened(Connection connection) + { + if (!isStarted()) + return; + + _connections.increment(); + } + + @Override + public void onClosed(Connection connection) + { + if (!isStarted()) + return; + + _connections.decrement(); + + long elapsed = System.currentTimeMillis() - connection.getCreatedTimeStamp(); + _connectionsDuration.set(elapsed); + + long bytesIn = connection.getBytesIn(); + if (bytesIn > 0) + _rcvdBytes.add(bytesIn); + long bytesOut = connection.getBytesOut(); + if (bytesOut > 0) + _sentBytes.add(bytesOut); + + long messagesIn = connection.getMessagesIn(); + if (messagesIn > 0) + _messagesIn.add(messagesIn); + long messagesOut = connection.getMessagesOut(); + if (messagesOut > 0) + _messagesOut.add(messagesOut); + } + + @ManagedAttribute("Total number of bytes received by tracked connections") + public long getReceivedBytes() + { + return _rcvdBytes.sum(); + } + + @ManagedAttribute("Total number of bytes received per second since the last invocation of this method") + public long getReceivedBytesRate() + { + long now = System.nanoTime(); + long then = _bytesInStamp.getAndSet(now); + long elapsed = TimeUnit.NANOSECONDS.toMillis(now - then); + return elapsed == 0 ? 0 : getReceivedBytes() * 1000 / elapsed; + } + + @ManagedAttribute("Total number of bytes sent by tracked connections") + public long getSentBytes() + { + return _sentBytes.sum(); + } + + @ManagedAttribute("Total number of bytes sent per second since the last invocation of this method") + public long getSentBytesRate() + { + long now = System.nanoTime(); + long then = _bytesOutStamp.getAndSet(now); + long elapsed = TimeUnit.NANOSECONDS.toMillis(now - then); + return elapsed == 0 ? 0 : getSentBytes() * 1000 / elapsed; + } + + @ManagedAttribute("The max duration of a connection in ms") + public long getConnectionDurationMax() + { + return _connectionsDuration.getMax(); + } + + @ManagedAttribute("The mean duration of a connection in ms") + public double getConnectionDurationMean() + { + return _connectionsDuration.getMean(); + } + + @ManagedAttribute("The standard deviation of the duration of a connection") + public double getConnectionDurationStdDev() + { + return _connectionsDuration.getStdDev(); + } + + @ManagedAttribute("The total number of connections opened") + public long getConnectionsTotal() + { + return _connections.getTotal(); + } + + @ManagedAttribute("The current number of open connections") + public long getConnections() + { + return _connections.getCurrent(); + } + + @ManagedAttribute("The max number of open connections") + public long getConnectionsMax() + { + return _connections.getMax(); + } + + @ManagedAttribute("The total number of messages received") + public long getReceivedMessages() + { + return _messagesIn.sum(); + } + + @ManagedAttribute("Total number of messages received per second since the last invocation of this method") + public long getReceivedMessagesRate() + { + long now = System.nanoTime(); + long then = _messagesInStamp.getAndSet(now); + long elapsed = TimeUnit.NANOSECONDS.toMillis(now - then); + return elapsed == 0 ? 0 : getReceivedMessages() * 1000 / elapsed; + } + + @ManagedAttribute("The total number of messages sent") + public long getSentMessages() + { + return _messagesOut.sum(); + } + + @ManagedAttribute("Total number of messages sent per second since the last invocation of this method") + public long getSentMessagesRate() + { + long now = System.nanoTime(); + long then = _messagesOutStamp.getAndSet(now); + long elapsed = TimeUnit.NANOSECONDS.toMillis(now - then); + return elapsed == 0 ? 0 : getSentMessages() * 1000 / elapsed; + } + + @Override + public String dump() + { + return ContainerLifeCycle.dump(this); + } + + @Override + public void dump(Appendable out, String indent) throws IOException + { + ContainerLifeCycle.dumpObject(out, this); + List children = new ArrayList<>(); + children.add(String.format("connections=%s", _connections)); + children.add(String.format("durations=%s", _connectionsDuration)); + children.add(String.format("bytes in/out=%s/%s", getReceivedBytes(), getSentBytes())); + children.add(String.format("messages in/out=%s/%s", getReceivedMessages(), getSentMessages())); + ContainerLifeCycle.dump(out, indent, children); + } + + @Override + public String toString() + { + return String.format("%s@%x", getClass().getSimpleName(), hashCode()); + } +} diff --git a/jetty-server/src/main/config/etc/jetty-stats.xml b/jetty-server/src/main/config/etc/jetty-stats.xml index 445ae6a8a43..954acd761df 100644 --- a/jetty-server/src/main/config/etc/jetty-stats.xml +++ b/jetty-server/src/main/config/etc/jetty-stats.xml @@ -12,7 +12,7 @@ - + diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectorStatistics.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectorStatistics.java index e73cdc6da2d..4e97aece369 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectorStatistics.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectorStatistics.java @@ -43,7 +43,10 @@ import org.eclipse.jetty.util.statistic.SampleStatistic; /** A Connector.Listener that gathers Connector and Connections Statistics. * Adding an instance of this class as with {@link AbstractConnector#addBean(Object)} * will register the listener with all connections accepted by that connector. + * + * @deprecated use {@link ServerConnectionStatistics} instead. */ +@Deprecated @ManagedObject("Connector Statistics") public class ConnectorStatistics extends AbstractLifeCycle implements Dumpable, Connection.Listener { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnectionStatistics.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnectionStatistics.java new file mode 100644 index 00000000000..91452f4ea61 --- /dev/null +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnectionStatistics.java @@ -0,0 +1,34 @@ +// +// ======================================================================== +// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// 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.server; + +import org.eclipse.jetty.io.ConnectionStatistics; +import org.eclipse.jetty.util.component.Container; + +public class ServerConnectionStatistics extends ConnectionStatistics +{ + public static void addToAllConnectors(Server server) + { + for (Connector connector : server.getConnectors()) + { + if (connector instanceof Container) + ((Container)connector).addBean(new ConnectionStatistics()); + } + } +}