Merge branch 'jetty-9.4.x' of github.com:eclipse/jetty.project into jetty-9.4.x
This commit is contained in:
commit
3ca6f95e0a
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||||
|
|
||||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||||
<Ref refid="DeploymentManager">
|
<Ref refid="DeploymentManager">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||||
|
|
||||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||||
<Ref id="httpConnector">
|
<Ref id="httpConnector">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||||
|
|
||||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||||
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||||
|
|
||||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||||
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||||
|
|
||||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||||
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||||
|
|
||||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||||
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||||
|
|
||||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||||
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
The ThreadMonitor is distributed as part of the jetty-monitor module.
|
|
||||||
|
|
||||||
In order to start ThreadMonitor when server starts up, the following command line should be used.
|
|
||||||
|
|
||||||
java -jar start.jar OPTIONS=monitor jetty-monitor.xml
|
|
||||||
|
|
||||||
To run ThreadMonitor on a Jetty installation that doesn't include jetty-monitor module, the jetty-monitor-[version].jar file needs to be copied into ${jetty.home}/lib/ext directory, and jetty-monitor.xml configuration file needs to be copied into ${jetty.home}/etc directory. Subsequently, the following command line should be used.
|
|
||||||
|
|
||||||
java -jar start.jar etc/jetty-monitor.xml
|
|
||||||
|
|
||||||
If running Jetty on Java VM version 1.5, the -Dcom.sun.management.jmxremote option should be added to the command lines above in order to enable the JMX agent.
|
|
||||||
|
|
||||||
In order to log CPU utilization for threads that are above specified threshold, you need to follow instructions inside jetty-monitor.xml configuration file.
|
|
|
@ -1,84 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
|
||||||
<parent>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-project</artifactId>
|
|
||||||
<version>9.4.0-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>jetty-monitor</artifactId>
|
|
||||||
<name>Jetty :: Monitoring</name>
|
|
||||||
<url>http://www.eclipse.org/jetty</url>
|
|
||||||
<description>Performance monitoring artifact for jetty.</description>
|
|
||||||
<properties>
|
|
||||||
<bundle-symbolic-name>${project.groupId}.monitor</bundle-symbolic-name>
|
|
||||||
</properties>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<forkMode>always</forkMode>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>findbugs-maven-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<onlyAnalyze>org.eclipse.jetty.monitor.*</onlyAnalyze>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-util</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-io</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-http</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-xml</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-client</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-jmx</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<!--dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-websocket</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-server</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
|
||||||
<artifactId>jetty-test-helper</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
|
@ -1,30 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
|
||||||
|
|
||||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
|
||||||
<!-- Create Thread Monitor, and add to the Server as a lifecycle -->
|
|
||||||
<Call name="addBean">
|
|
||||||
<Arg>
|
|
||||||
<New class="org.eclipse.jetty.monitor.ThreadMonitor">
|
|
||||||
<Set name="scanInterval">2000</Set>
|
|
||||||
<Set name="busyThreshold">90</Set>
|
|
||||||
<Set name="stackDepth">3</Set>
|
|
||||||
<Set name="trailLength">2</Set>
|
|
||||||
<!-- To enable logging CPU utilization for threads above specified threshold, -->
|
|
||||||
<!-- uncomment the following lines, changing log interval (in milliseconds) -->
|
|
||||||
<!-- and log threshold (in percent) as desired. -->
|
|
||||||
<!--
|
|
||||||
<Set name="logInterval">10000</Set>
|
|
||||||
<Set name="logThreshold">1</Set>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- To enable detail dump of the server whenever a thread is detected as spinning, -->
|
|
||||||
<!-- uncomment the following lines. -->
|
|
||||||
<!--
|
|
||||||
<Set name="dumpable"><Ref refid="Server"/></Set>
|
|
||||||
-->
|
|
||||||
</New>
|
|
||||||
</Arg>
|
|
||||||
</Call>
|
|
||||||
</Configure>
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
[description]
|
|
||||||
Enables the Jetty Monitor Module to periodically
|
|
||||||
check/publish JMX parameters of the server.
|
|
||||||
|
|
||||||
[depend]
|
|
||||||
server
|
|
||||||
client
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
lib/monitor/jetty-monitor-${jetty.version}.jar
|
|
||||||
|
|
||||||
[xml]
|
|
||||||
etc/jetty-monitor.xml
|
|
|
@ -1,193 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.management.MBeanServerConnection;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.monitor.jmx.MonitorAction;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.MonitorTask;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.ServiceConnection;
|
|
||||||
import org.eclipse.jetty.xml.XmlConfiguration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JMXMonitor
|
|
||||||
* <p>
|
|
||||||
* Performs monitoring of the values of the attributes of MBeans
|
|
||||||
* and executes specified actions as well as sends notifications
|
|
||||||
* of the specified events that have occurred.
|
|
||||||
*/
|
|
||||||
public class JMXMonitor
|
|
||||||
{
|
|
||||||
private static JMXMonitor __monitor = new JMXMonitor();
|
|
||||||
|
|
||||||
private String _serverUrl;
|
|
||||||
private ServiceConnection _serviceConnection;
|
|
||||||
|
|
||||||
private Set<MonitorAction> _actions = new HashSet<MonitorAction>();
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Constructs a JMXMonitor instance. Used for XML Configuration.
|
|
||||||
*
|
|
||||||
* !! DO NOT INSTANTIATE EXPLICITLY !!
|
|
||||||
*/
|
|
||||||
public JMXMonitor() {}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Adds monitor actions to the monitor
|
|
||||||
*
|
|
||||||
* @param actions monitor actions to add
|
|
||||||
* @return true if successful
|
|
||||||
*/
|
|
||||||
public boolean addActions(MonitorAction... actions)
|
|
||||||
{
|
|
||||||
return getInstance().add(actions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Removes monitor actions from the monitor
|
|
||||||
*
|
|
||||||
* @param actions monitor actions to remove
|
|
||||||
* @return true if successful
|
|
||||||
*/
|
|
||||||
public boolean removeActions(MonitorAction... actions)
|
|
||||||
{
|
|
||||||
return getInstance().remove(actions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Sets the JMX server URL
|
|
||||||
*
|
|
||||||
* @param url URL of the JMX server
|
|
||||||
*/
|
|
||||||
public void setUrl(String url)
|
|
||||||
{
|
|
||||||
getInstance().set(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MBeanServerConnection getConnection()
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
return getInstance().get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JMXMonitor getInstance()
|
|
||||||
{
|
|
||||||
return __monitor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean addMonitorActions(MonitorAction... actions)
|
|
||||||
{
|
|
||||||
return getInstance().add(actions);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean removeMonitorActions(MonitorAction... actions)
|
|
||||||
{
|
|
||||||
return getInstance().remove(actions);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setServiceUrl(String url)
|
|
||||||
{
|
|
||||||
getInstance().set(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieves a connection to JMX service
|
|
||||||
*
|
|
||||||
* @return server connection
|
|
||||||
* @throws IOException if unable to obtain server connection
|
|
||||||
*/
|
|
||||||
public static MBeanServerConnection getServiceConnection()
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
return getInstance().getConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(final String args[]) throws Exception
|
|
||||||
{
|
|
||||||
XmlConfiguration.main(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized boolean add(MonitorAction... actions)
|
|
||||||
{
|
|
||||||
boolean result = true;
|
|
||||||
|
|
||||||
for (MonitorAction action : actions)
|
|
||||||
{
|
|
||||||
if (!_actions.add(action))
|
|
||||||
{
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MonitorTask.schedule(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized boolean remove(MonitorAction... actions)
|
|
||||||
{
|
|
||||||
boolean result = true;
|
|
||||||
|
|
||||||
for (MonitorAction action : actions)
|
|
||||||
{
|
|
||||||
if (!_actions.remove(action))
|
|
||||||
{
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MonitorTask.cancel(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void set(String url)
|
|
||||||
{
|
|
||||||
_serverUrl = url;
|
|
||||||
|
|
||||||
if (_serviceConnection != null)
|
|
||||||
{
|
|
||||||
_serviceConnection.disconnect();
|
|
||||||
_serviceConnection = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized MBeanServerConnection get()
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
if (_serviceConnection == null)
|
|
||||||
{
|
|
||||||
_serviceConnection = new ServiceConnection(_serverUrl);
|
|
||||||
_serviceConnection.connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _serviceConnection.getConnection();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,610 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor;
|
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import java.lang.management.ThreadMXBean;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.monitor.thread.ThreadMonitorException;
|
|
||||||
import org.eclipse.jetty.monitor.thread.ThreadMonitorInfo;
|
|
||||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
|
||||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
|
||||||
import org.eclipse.jetty.util.component.Dumpable;
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
|
||||||
|
|
||||||
@ManagedObject("Busy Thread Monitor")
|
|
||||||
public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
|
||||||
{
|
|
||||||
private static final Logger LOG = Log.getLogger(ThreadMonitor.class);
|
|
||||||
|
|
||||||
private int _scanInterval;
|
|
||||||
private int _logInterval;
|
|
||||||
private int _busyThreshold;
|
|
||||||
private int _logThreshold;
|
|
||||||
private int _stackDepth;
|
|
||||||
private int _trailLength;
|
|
||||||
|
|
||||||
private ThreadMXBean _threadBean;
|
|
||||||
|
|
||||||
private Thread _runner;
|
|
||||||
private Logger _logger;
|
|
||||||
private volatile boolean _done = true;
|
|
||||||
private Dumpable _dumpable;
|
|
||||||
|
|
||||||
private Map<Long,ThreadMonitorInfo> _monitorInfo;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Instantiates a new thread monitor.
|
|
||||||
*
|
|
||||||
* @throws Exception if unable to instantiate thread monitor
|
|
||||||
*/
|
|
||||||
public ThreadMonitor() throws Exception
|
|
||||||
{
|
|
||||||
this(5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Instantiates a new thread monitor.
|
|
||||||
*
|
|
||||||
* @param intervalMs scan interval
|
|
||||||
* @throws Exception if unable to instantiate thread monitor
|
|
||||||
*/
|
|
||||||
public ThreadMonitor(int intervalMs) throws Exception
|
|
||||||
{
|
|
||||||
this(intervalMs, 95);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Instantiates a new thread monitor.
|
|
||||||
*
|
|
||||||
* @param intervalMs scan interval
|
|
||||||
* @param threshold busy threshold
|
|
||||||
* @throws Exception if unable to instantiate thread monitor
|
|
||||||
*/
|
|
||||||
public ThreadMonitor(int intervalMs, int threshold) throws Exception
|
|
||||||
{
|
|
||||||
this(intervalMs, threshold, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Instantiates a new thread monitor.
|
|
||||||
*
|
|
||||||
* @param intervalMs scan interval
|
|
||||||
* @param threshold busy threshold
|
|
||||||
* @param depth stack compare depth
|
|
||||||
* @throws Exception if unable to instantiate thread monitor
|
|
||||||
*/
|
|
||||||
public ThreadMonitor(int intervalMs, int threshold, int depth) throws Exception
|
|
||||||
{
|
|
||||||
this(intervalMs, threshold, depth, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Instantiates a new thread monitor.
|
|
||||||
*
|
|
||||||
* @param intervalMs scan interval
|
|
||||||
* @param threshold busy threshold
|
|
||||||
* @param depth stack compare depth
|
|
||||||
* @param trail length of stack trail
|
|
||||||
* @throws Exception if unable to instantiate thread monitor
|
|
||||||
*/
|
|
||||||
public ThreadMonitor(int intervalMs, int threshold, int depth, int trail) throws Exception
|
|
||||||
{
|
|
||||||
_scanInterval = intervalMs;
|
|
||||||
_busyThreshold = threshold;
|
|
||||||
_stackDepth = depth;
|
|
||||||
_trailLength = trail;
|
|
||||||
|
|
||||||
_logger = Log.getLogger(ThreadMonitor.class.getName());
|
|
||||||
_monitorInfo = new HashMap<Long, ThreadMonitorInfo>();
|
|
||||||
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Gets the scan interval.
|
|
||||||
*
|
|
||||||
* @return the scan interval
|
|
||||||
*/
|
|
||||||
public int getScanInterval()
|
|
||||||
{
|
|
||||||
return _scanInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Sets the scan interval.
|
|
||||||
*
|
|
||||||
* @param ms the new scan interval
|
|
||||||
*/
|
|
||||||
public void setScanInterval(int ms)
|
|
||||||
{
|
|
||||||
_scanInterval = ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Gets the log interval.
|
|
||||||
*
|
|
||||||
* @return the log interval
|
|
||||||
*/
|
|
||||||
public int getLogInterval()
|
|
||||||
{
|
|
||||||
return _logInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Sets the log interval.
|
|
||||||
*
|
|
||||||
* @param ms the new log interval
|
|
||||||
*/
|
|
||||||
public void setLogInterval(int ms)
|
|
||||||
{
|
|
||||||
_logInterval = ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Gets the busy threshold.
|
|
||||||
*
|
|
||||||
* @return the busy threshold
|
|
||||||
*/
|
|
||||||
public int getBusyThreshold()
|
|
||||||
{
|
|
||||||
return _busyThreshold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Sets the busy threshold.
|
|
||||||
*
|
|
||||||
* @param percent the new busy threshold
|
|
||||||
*/
|
|
||||||
public void setBusyThreshold(int percent)
|
|
||||||
{
|
|
||||||
_busyThreshold = percent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Gets the log threshold.
|
|
||||||
*
|
|
||||||
* @return the log threshold
|
|
||||||
*/
|
|
||||||
public int getLogThreshold()
|
|
||||||
{
|
|
||||||
return _logThreshold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Sets the log threshold.
|
|
||||||
*
|
|
||||||
* @param percent the new log threshold
|
|
||||||
*/
|
|
||||||
public void setLogThreshold(int percent)
|
|
||||||
{
|
|
||||||
_logThreshold = percent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Gets the stack depth.
|
|
||||||
*
|
|
||||||
* @return the stack depth
|
|
||||||
*/
|
|
||||||
public int getStackDepth()
|
|
||||||
{
|
|
||||||
return _stackDepth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Sets the stack depth.
|
|
||||||
*
|
|
||||||
* @param stackDepth the new stack depth
|
|
||||||
*/
|
|
||||||
public void setStackDepth(int stackDepth)
|
|
||||||
{
|
|
||||||
_stackDepth = stackDepth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Sets the stack trace trail length.
|
|
||||||
*
|
|
||||||
* @param trailLength the new trail length
|
|
||||||
*/
|
|
||||||
public void setTrailLength(int trailLength)
|
|
||||||
{
|
|
||||||
_trailLength = trailLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Gets the stack trace trail length.
|
|
||||||
*
|
|
||||||
* @return the trail length
|
|
||||||
*/
|
|
||||||
public int getTrailLength()
|
|
||||||
{
|
|
||||||
return _trailLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Enable logging of CPU usage.
|
|
||||||
*
|
|
||||||
* @param frequencyMs the logging frequency
|
|
||||||
* @param thresholdPercent the logging threshold
|
|
||||||
*/
|
|
||||||
public void logCpuUsage(int frequencyMs, int thresholdPercent)
|
|
||||||
{
|
|
||||||
setLogInterval(frequencyMs);
|
|
||||||
setLogThreshold(thresholdPercent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @return A {@link Dumpable} that is dumped whenever spinning threads are detected
|
|
||||||
*/
|
|
||||||
public Dumpable getDumpable()
|
|
||||||
{
|
|
||||||
return _dumpable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @param dumpable A {@link Dumpable} that is dumped whenever spinning threads are detected
|
|
||||||
*/
|
|
||||||
public void setDumpable(Dumpable dumpable)
|
|
||||||
{
|
|
||||||
_dumpable = dumpable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
|
|
||||||
*/
|
|
||||||
public void doStart()
|
|
||||||
{
|
|
||||||
_done = false;
|
|
||||||
|
|
||||||
_runner = new Thread(this);
|
|
||||||
_runner.setDaemon(true);
|
|
||||||
_runner.start();
|
|
||||||
|
|
||||||
LOG.info("Thread Monitor started successfully");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
|
|
||||||
*/
|
|
||||||
public void doStop()
|
|
||||||
{
|
|
||||||
if (_runner != null)
|
|
||||||
{
|
|
||||||
_done = true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_runner.join();
|
|
||||||
}
|
|
||||||
catch (InterruptedException ex) {}
|
|
||||||
|
|
||||||
_monitorInfo.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve all avaliable thread ids
|
|
||||||
*
|
|
||||||
* @return array of thread ids
|
|
||||||
*/
|
|
||||||
protected long[] getAllThreadIds()
|
|
||||||
{
|
|
||||||
return _threadBean.getAllThreadIds();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve the cpu time for specified thread.
|
|
||||||
*
|
|
||||||
* @param id thread id
|
|
||||||
* @return cpu time of the thread
|
|
||||||
*/
|
|
||||||
protected long getThreadCpuTime(long id)
|
|
||||||
{
|
|
||||||
return _threadBean.getThreadCpuTime(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Initialize JMX objects.
|
|
||||||
*/
|
|
||||||
protected void init()
|
|
||||||
{
|
|
||||||
_threadBean = ManagementFactory.getThreadMXBean();
|
|
||||||
if (_threadBean.isThreadCpuTimeSupported())
|
|
||||||
{
|
|
||||||
_threadBean.setThreadCpuTimeEnabled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see java.lang.Runnable#run()
|
|
||||||
*/
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
// Initialize repeat flag
|
|
||||||
boolean repeat = false;
|
|
||||||
boolean scanNow, logNow;
|
|
||||||
|
|
||||||
// Set next scan time and log time
|
|
||||||
long nextScanTime = System.currentTimeMillis();
|
|
||||||
long nextLogTime = nextScanTime + _logInterval;
|
|
||||||
|
|
||||||
while (!_done)
|
|
||||||
{
|
|
||||||
long currTime = System.currentTimeMillis();
|
|
||||||
scanNow = (currTime > nextScanTime);
|
|
||||||
logNow = (_logInterval > 0 && currTime > nextLogTime);
|
|
||||||
if (repeat || scanNow || logNow)
|
|
||||||
{
|
|
||||||
repeat = collectThreadInfo();
|
|
||||||
logThreadInfo(logNow);
|
|
||||||
|
|
||||||
if (scanNow)
|
|
||||||
{
|
|
||||||
nextScanTime = System.currentTimeMillis() + _scanInterval;
|
|
||||||
}
|
|
||||||
if (logNow)
|
|
||||||
{
|
|
||||||
nextLogTime = System.currentTimeMillis() + _logInterval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sleep only if not going to repeat scanning immediately
|
|
||||||
if (!repeat)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
catch (InterruptedException ex)
|
|
||||||
{
|
|
||||||
LOG.ignore(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Collect thread info.
|
|
||||||
*/
|
|
||||||
private boolean collectThreadInfo()
|
|
||||||
{
|
|
||||||
boolean repeat = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Retrieve stack traces for all threads at once as it
|
|
||||||
// was proven to be an order of magnitude faster when
|
|
||||||
// retrieving a single thread stack trace.
|
|
||||||
Map<Thread,StackTraceElement[]> all = Thread.getAllStackTraces();
|
|
||||||
|
|
||||||
Set<Long> newOrUpdatedIds = new HashSet<Long>();
|
|
||||||
|
|
||||||
for (Map.Entry<Thread,StackTraceElement[]> entry : all.entrySet())
|
|
||||||
{
|
|
||||||
Thread thread = entry.getKey();
|
|
||||||
long threadId = thread.getId();
|
|
||||||
|
|
||||||
// Skip our own runner thread
|
|
||||||
if (threadId == _runner.getId())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ThreadMonitorInfo currMonitorInfo = _monitorInfo.get(Long.valueOf(threadId));
|
|
||||||
if (currMonitorInfo == null)
|
|
||||||
{
|
|
||||||
// Create thread info object for a new thread
|
|
||||||
currMonitorInfo = new ThreadMonitorInfo(thread);
|
|
||||||
currMonitorInfo.setStackTrace(entry.getValue());
|
|
||||||
currMonitorInfo.setCpuTime(getThreadCpuTime(threadId));
|
|
||||||
currMonitorInfo.setSampleTime(System.nanoTime());
|
|
||||||
_monitorInfo.put(Long.valueOf(threadId), currMonitorInfo);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Update the existing thread info object
|
|
||||||
currMonitorInfo.setStackTrace(entry.getValue());
|
|
||||||
currMonitorInfo.setCpuTime(getThreadCpuTime(threadId));
|
|
||||||
currMonitorInfo.setSampleTime(System.nanoTime());
|
|
||||||
|
|
||||||
// Stack trace count holds logging state
|
|
||||||
int count = currMonitorInfo.getTraceCount();
|
|
||||||
if (count >= 0 && currMonitorInfo.isSpinning())
|
|
||||||
{
|
|
||||||
// Thread was spinning and was logged before
|
|
||||||
if (count < _trailLength)
|
|
||||||
{
|
|
||||||
// Log another stack trace
|
|
||||||
currMonitorInfo.setTraceCount(count+1);
|
|
||||||
repeat = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset spin flag and trace count
|
|
||||||
currMonitorInfo.setSpinning(false);
|
|
||||||
currMonitorInfo.setTraceCount(-1);
|
|
||||||
}
|
|
||||||
if (currMonitorInfo.getCpuUtilization() > _busyThreshold)
|
|
||||||
{
|
|
||||||
// Thread is busy
|
|
||||||
StackTraceElement[] lastStackTrace = currMonitorInfo.getStackTrace();
|
|
||||||
|
|
||||||
if (lastStackTrace != null
|
|
||||||
&& matchStackTraces(lastStackTrace, entry.getValue()))
|
|
||||||
{
|
|
||||||
// Thread is spinning
|
|
||||||
currMonitorInfo.setSpinning(true);
|
|
||||||
if (count < 0)
|
|
||||||
{
|
|
||||||
// Enable logging of spin status and stack traces
|
|
||||||
// only if the incoming trace count is negative
|
|
||||||
// that indicates a new scan for this thread
|
|
||||||
currMonitorInfo.setTraceCount(0);
|
|
||||||
repeat = (_trailLength > 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newOrUpdatedIds.add(Long.valueOf(threadId));
|
|
||||||
}
|
|
||||||
|
|
||||||
//clean out threads that no longer exist
|
|
||||||
Iterator<Long> iter = _monitorInfo.keySet().iterator();
|
|
||||||
while (iter.hasNext())
|
|
||||||
{
|
|
||||||
Long id = iter.next();
|
|
||||||
if (!newOrUpdatedIds.contains(id))
|
|
||||||
iter.remove();
|
|
||||||
}
|
|
||||||
newOrUpdatedIds.clear();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
LOG.debug(ex);
|
|
||||||
}
|
|
||||||
return repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
protected void logThreadInfo(boolean logAll)
|
|
||||||
{
|
|
||||||
if (_monitorInfo.size() > 0)
|
|
||||||
{
|
|
||||||
// Select thread objects for all live threads
|
|
||||||
long[] running = getAllThreadIds();
|
|
||||||
List<ThreadMonitorInfo> all = new ArrayList<ThreadMonitorInfo>();
|
|
||||||
for (int idx=0; idx<running.length; idx++)
|
|
||||||
{
|
|
||||||
ThreadMonitorInfo info = _monitorInfo.get(running[idx]);
|
|
||||||
if (info != null)
|
|
||||||
{
|
|
||||||
all.add(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort selected thread objects by their CPU utilization
|
|
||||||
Collections.sort(all, new Comparator<ThreadMonitorInfo>()
|
|
||||||
{
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public int compare(ThreadMonitorInfo info1, ThreadMonitorInfo info2)
|
|
||||||
{
|
|
||||||
return (int)Math.signum(info2.getCpuUtilization()-info1.getCpuUtilization());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
String format = "Thread '%2$s'[%3$s,id:%1$d,cpu:%4$.2f%%]%5$s";
|
|
||||||
|
|
||||||
// Log thread information for threads that exceed logging threshold
|
|
||||||
// or log spinning threads if their trace count is zero
|
|
||||||
boolean spinning=false;
|
|
||||||
for (ThreadMonitorInfo info : all)
|
|
||||||
{
|
|
||||||
if (logAll && info.getCpuUtilization() > _logThreshold
|
|
||||||
|| info.isSpinning() && info.getTraceCount() == 0)
|
|
||||||
{
|
|
||||||
String message = String.format(format,
|
|
||||||
info.getThreadId(), info.getThreadName(),
|
|
||||||
info.getThreadState(), info.getCpuUtilization(),
|
|
||||||
info.isSpinning() ? " SPINNING" : "");
|
|
||||||
_logger.info(message);
|
|
||||||
spinning=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dump info
|
|
||||||
if (spinning && _dumpable!=null)
|
|
||||||
{
|
|
||||||
System.err.println(_dumpable.dump());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log stack traces for spinning threads with positive trace count
|
|
||||||
for (ThreadMonitorInfo info : all)
|
|
||||||
{
|
|
||||||
if (info.isSpinning() && info.getTraceCount() >= 0)
|
|
||||||
{
|
|
||||||
String message = String.format(format,
|
|
||||||
info.getThreadId(), info.getThreadName(),
|
|
||||||
info.getThreadState(), info.getCpuUtilization(),
|
|
||||||
" STACK TRACE");
|
|
||||||
_logger.warn(new ThreadMonitorException(message, info.getStackTrace()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Match stack traces.
|
|
||||||
*
|
|
||||||
* @param lastStackTrace last stack trace
|
|
||||||
* @param stackTrace current stack trace
|
|
||||||
* @return true, if successful
|
|
||||||
*/
|
|
||||||
private boolean matchStackTraces(StackTraceElement[] lastStackTrace, StackTraceElement[] stackTrace)
|
|
||||||
{
|
|
||||||
boolean match = true;
|
|
||||||
int count = Math.min(_stackDepth, Math.min(lastStackTrace.length, stackTrace.length));
|
|
||||||
|
|
||||||
for (int idx=0; idx < count; idx++)
|
|
||||||
{
|
|
||||||
if (!stackTrace[idx].equals(lastStackTrace[idx]))
|
|
||||||
{
|
|
||||||
match = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,409 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.integration;
|
|
||||||
|
|
||||||
import static java.lang.Integer.parseInt;
|
|
||||||
import static java.lang.System.getProperty;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.management.MBeanServerConnection;
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.client.HttpClient;
|
|
||||||
import org.eclipse.jetty.client.api.ContentResponse;
|
|
||||||
import org.eclipse.jetty.client.util.BytesContentProvider;
|
|
||||||
import org.eclipse.jetty.http.HttpStatus;
|
|
||||||
import org.eclipse.jetty.monitor.JMXMonitor;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventNotifier;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventState;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventState.TriggerState;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventTrigger;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.MonitorAction;
|
|
||||||
import org.eclipse.jetty.monitor.triggers.AggregateEventTrigger;
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
|
||||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
|
||||||
|
|
||||||
public class JavaMonitorAction extends MonitorAction
|
|
||||||
{
|
|
||||||
private static final Logger LOG = Log.getLogger(JavaMonitorAction.class);
|
|
||||||
|
|
||||||
private final HttpClient _client;
|
|
||||||
|
|
||||||
private final String _url;
|
|
||||||
private final String _uuid;
|
|
||||||
private final String _appid;
|
|
||||||
|
|
||||||
private String _srvip;
|
|
||||||
private String _session;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public JavaMonitorAction(EventNotifier notifier, String url, String uuid, String appid, long pollInterval)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
super(new AggregateEventTrigger(),notifier,pollInterval);
|
|
||||||
|
|
||||||
_url = url;
|
|
||||||
_uuid = uuid;
|
|
||||||
_appid = appid;
|
|
||||||
|
|
||||||
QueuedThreadPool executor = new QueuedThreadPool();
|
|
||||||
executor.setName(executor.getName() + "-monitor");
|
|
||||||
_client = new HttpClient();
|
|
||||||
_client.setExecutor(executor);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_client.start();
|
|
||||||
_srvip = getServerIP();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
LOG.debug(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
sendData(new Properties());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.monitor.jmx.MonitorAction#execute(org.eclipse.jetty.monitor.jmx.EventTrigger, org.eclipse.jetty.monitor.jmx.EventState, long)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void execute(EventTrigger trigger, EventState<?> state, long timestamp)
|
|
||||||
{
|
|
||||||
exec(trigger, state, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @param trigger
|
|
||||||
* @param state
|
|
||||||
* @param timestamp
|
|
||||||
*/
|
|
||||||
private <T> void exec(EventTrigger trigger, EventState<T> state, long timestamp)
|
|
||||||
{
|
|
||||||
Collection<TriggerState<T>> trs = state.values();
|
|
||||||
|
|
||||||
Properties data = new Properties();
|
|
||||||
for (TriggerState<T> ts : trs)
|
|
||||||
{
|
|
||||||
Object value = ts.getValue();
|
|
||||||
|
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
buffer.append(value == null ? "" : value.toString());
|
|
||||||
buffer.append("|");
|
|
||||||
buffer.append(getClassID(value));
|
|
||||||
buffer.append("||");
|
|
||||||
buffer.append(ts.getDescription());
|
|
||||||
|
|
||||||
data.setProperty(ts.getID(), buffer.toString());
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
sendData(data);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
LOG.debug(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @param data
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private void sendData(Properties data)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
data.put("account", _uuid);
|
|
||||||
data.put("appserver", "Jetty");
|
|
||||||
data.put("localIp", _srvip);
|
|
||||||
if (_appid == null)
|
|
||||||
data.put("lowestPort", getHttpPort());
|
|
||||||
else
|
|
||||||
data.put("lowestPort", _appid);
|
|
||||||
if (_session != null)
|
|
||||||
data.put("session", _session);
|
|
||||||
|
|
||||||
Properties response = sendRequest(data);
|
|
||||||
|
|
||||||
parseResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @param request
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private Properties sendRequest(Properties request)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
ByteArrayOutputStream reqStream = null;
|
|
||||||
ByteArrayInputStream resStream = null;
|
|
||||||
Properties response = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
reqStream = new ByteArrayOutputStream();
|
|
||||||
request.storeToXML(reqStream,null);
|
|
||||||
|
|
||||||
ContentResponse r3sponse = _client.POST(_url)
|
|
||||||
.header("Connection","close")
|
|
||||||
.content(new BytesContentProvider(reqStream.toByteArray()))
|
|
||||||
.send();
|
|
||||||
|
|
||||||
|
|
||||||
if (r3sponse.getStatus() == HttpStatus.OK_200)
|
|
||||||
{
|
|
||||||
response = new Properties();
|
|
||||||
resStream = new ByteArrayInputStream(r3sponse.getContent());
|
|
||||||
response.loadFromXML(resStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (reqStream != null)
|
|
||||||
reqStream.close();
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
LOG.ignore(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (resStream != null)
|
|
||||||
resStream.close();
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
LOG.ignore(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
private void parseResponse(Properties response)
|
|
||||||
{
|
|
||||||
if (response.get("onhold") != null)
|
|
||||||
throw new Error("Suspended");
|
|
||||||
|
|
||||||
|
|
||||||
if (response.get("session") != null)
|
|
||||||
{
|
|
||||||
_session = (String) response.remove("session");
|
|
||||||
|
|
||||||
AggregateEventTrigger trigger = (AggregateEventTrigger)getTrigger();
|
|
||||||
|
|
||||||
String queryString;
|
|
||||||
ObjectName[] queryResults;
|
|
||||||
for (Map.Entry<Object, Object> entry : response.entrySet())
|
|
||||||
{
|
|
||||||
String[] values = ((String) entry.getValue()).split("\\|");
|
|
||||||
|
|
||||||
queryString = values[0];
|
|
||||||
if (queryString.startsWith("com.javamonitor.openfire"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (queryString.startsWith("com.javamonitor"))
|
|
||||||
{
|
|
||||||
queryString = "org.eclipse.jetty.monitor.integration:type=javamonitortools,id=0";
|
|
||||||
}
|
|
||||||
|
|
||||||
queryResults = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
queryResults = queryNames(queryString);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
LOG.debug(e);
|
|
||||||
}
|
|
||||||
catch (MalformedObjectNameException e)
|
|
||||||
{
|
|
||||||
LOG.debug(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queryResults != null)
|
|
||||||
{
|
|
||||||
int idx = 0;
|
|
||||||
for(ObjectName objName : queryResults)
|
|
||||||
{
|
|
||||||
String id = entry.getKey().toString()+(idx == 0 ? "" : ":"+idx);
|
|
||||||
String name = queryString.equals(objName.toString()) ? "" : objName.toString();
|
|
||||||
boolean repeat = Boolean.parseBoolean(values[2]);
|
|
||||||
trigger.add(new JavaMonitorTrigger(objName, values[1], id, name, repeat));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @param value
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private int getClassID(final Object value)
|
|
||||||
{
|
|
||||||
if (value == null)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (value instanceof Byte ||
|
|
||||||
value instanceof Short ||
|
|
||||||
value instanceof Integer ||
|
|
||||||
value instanceof Long)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (value instanceof Float ||
|
|
||||||
value instanceof Double)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (value instanceof Boolean)
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
return 4; // String
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private String getServerIP()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
Socket s = null;
|
|
||||||
try {
|
|
||||||
if (getProperty("http.proxyHost") != null)
|
|
||||||
{
|
|
||||||
s = new Socket(getProperty("http.proxyHost"),
|
|
||||||
parseInt(getProperty("http.proxyPort", "80")));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int port = 80;
|
|
||||||
|
|
||||||
URL url = new URL(_url);
|
|
||||||
if (url.getPort() != -1) {
|
|
||||||
port = url.getPort();
|
|
||||||
}
|
|
||||||
s = new Socket(url.getHost(), port);
|
|
||||||
}
|
|
||||||
return s.getLocalAddress().getHostAddress();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (s != null)
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
LOG.ignore(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Integer getHttpPort()
|
|
||||||
{
|
|
||||||
Collection<ObjectName> connectors = null;
|
|
||||||
MBeanServerConnection service;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
service = JMXMonitor.getServiceConnection();
|
|
||||||
|
|
||||||
connectors = service.queryNames(new ObjectName("org.eclipse.jetty.nio:type=selectchannelconnector,*"), null);
|
|
||||||
if (connectors != null && connectors.size() > 0)
|
|
||||||
{
|
|
||||||
Integer lowest = Integer.MAX_VALUE;
|
|
||||||
for (final ObjectName connector : connectors) {
|
|
||||||
lowest = (Integer)service.getAttribute(connector, "port");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lowest < Integer.MAX_VALUE)
|
|
||||||
return lowest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
LOG.debug(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @param param
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
* @throws NullPointerException
|
|
||||||
* @throws MalformedObjectNameException
|
|
||||||
*/
|
|
||||||
private ObjectName[] queryNames(ObjectName param)
|
|
||||||
throws IOException, MalformedObjectNameException
|
|
||||||
{
|
|
||||||
ObjectName[] result = null;
|
|
||||||
|
|
||||||
MBeanServerConnection connection = JMXMonitor.getServiceConnection();
|
|
||||||
Set names = connection.queryNames(param, null);
|
|
||||||
if (names != null && names.size() > 0)
|
|
||||||
{
|
|
||||||
result = new ObjectName[names.size()];
|
|
||||||
|
|
||||||
int idx = 0;
|
|
||||||
for(Object name : names)
|
|
||||||
{
|
|
||||||
if (name instanceof ObjectName)
|
|
||||||
result[idx++] = (ObjectName)name;
|
|
||||||
else
|
|
||||||
result[idx++] = new ObjectName(name.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObjectName[] queryNames(String param)
|
|
||||||
throws IOException, MalformedObjectNameException
|
|
||||||
{
|
|
||||||
return queryNames(new ObjectName(param));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,288 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.integration;
|
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import java.lang.management.ThreadInfo;
|
|
||||||
import java.lang.management.ThreadMXBean;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.security.Security;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
|
||||||
import org.eclipse.jetty.util.annotation.ManagedOperation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Derived from the JMX bean classes created by Kees Jan Koster for the java-monitor
|
|
||||||
* J2EE probe http://code.google.com/p/java-monitor-probes/source/browse/.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:kjkoster@gmail.com">Kees Jan Koster</a>
|
|
||||||
*/
|
|
||||||
@ManagedObject("Java Monitoring Tools")
|
|
||||||
public class JavaMonitorTools
|
|
||||||
{
|
|
||||||
private static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
|
|
||||||
|
|
||||||
private static Method findDeadlockMethod = null;
|
|
||||||
|
|
||||||
static
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
findDeadlockMethod = ThreadMXBean.class.getMethod("findDeadlockedThreads");
|
|
||||||
}
|
|
||||||
catch (Exception ignored)
|
|
||||||
{
|
|
||||||
// this is a 1.5 JVM
|
|
||||||
try
|
|
||||||
{
|
|
||||||
findDeadlockMethod = ThreadMXBean.class.getMethod("findMonitorDeadlockedThreads");
|
|
||||||
}
|
|
||||||
catch (SecurityException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
catch (NoSuchMethodException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ThreadInfo[] findDeadlock()
|
|
||||||
throws IllegalAccessException, InvocationTargetException
|
|
||||||
{
|
|
||||||
final long[] threadIds = (long[])findDeadlockMethod.invoke(threadMXBean,(Object[])null);
|
|
||||||
|
|
||||||
if (threadIds == null || threadIds.length < 1)
|
|
||||||
{
|
|
||||||
// no deadlock, we're done
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final ThreadInfo[] threads = threadMXBean.getThreadInfo(threadIds,Integer.MAX_VALUE);
|
|
||||||
return threads;
|
|
||||||
}
|
|
||||||
@ManagedOperation(value="Detailed report on the deadlocked threads.", impact="ACTION_INFO")
|
|
||||||
public String getDeadlockStacktraces()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
final ThreadInfo[] threads = findDeadlock();
|
|
||||||
if (threads == null)
|
|
||||||
{
|
|
||||||
// no deadlock, we're done
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return stacktraces(threads,0);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
return e.getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int MAX_STACK = 10;
|
|
||||||
|
|
||||||
private String stacktraces(final ThreadInfo[] threads, final int i)
|
|
||||||
{
|
|
||||||
if (i >= threads.length)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
final ThreadInfo thread = threads[i];
|
|
||||||
|
|
||||||
final StringBuilder trace = new StringBuilder();
|
|
||||||
for (int stack_i = 0; stack_i < Math.min(thread.getStackTrace().length,MAX_STACK); stack_i++)
|
|
||||||
{
|
|
||||||
if (stack_i == (MAX_STACK - 1))
|
|
||||||
{
|
|
||||||
trace.append(" ...");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
trace.append(" at ").append(thread.getStackTrace()[stack_i]).append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "\"" + thread.getThreadName() + "\", id " + thread.getThreadId() + " is " + thread.getThreadState() + " on " + thread.getLockName()
|
|
||||||
+ ", owned by " + thread.getLockOwnerName() + ", id " + thread.getLockOwnerId() + "\n" + trace + "\n\n" + stacktraces(threads,i + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We keep track of the last time we sampled the thread states.
|
|
||||||
* It is a crude optimization to avoid having to query for the
|
|
||||||
* threads states very often.
|
|
||||||
*/
|
|
||||||
private long lastSampled = 0L;
|
|
||||||
|
|
||||||
private final Map<Thread.State, Integer> states = new HashMap<Thread.State, Integer>();
|
|
||||||
|
|
||||||
@ManagedOperation(value="Number of Blocked Threads")
|
|
||||||
public int getThreadsBlocked()
|
|
||||||
{
|
|
||||||
sampleThreads();
|
|
||||||
|
|
||||||
return states.get(Thread.State.BLOCKED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ManagedOperation(value="Number of New Threads", impact="ACTION_INFO")
|
|
||||||
public int getThreadsNew()
|
|
||||||
{
|
|
||||||
sampleThreads();
|
|
||||||
|
|
||||||
return states.get(Thread.State.NEW);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ManagedOperation(value="Number of Terminated Threads", impact="ACTION_INFO")
|
|
||||||
public int getThreadsTerminated()
|
|
||||||
{
|
|
||||||
sampleThreads();
|
|
||||||
|
|
||||||
return states.get(Thread.State.TERMINATED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ManagedOperation(value="Number of Sleeping and Waiting threads")
|
|
||||||
public int getThreadsTimedWaiting()
|
|
||||||
{
|
|
||||||
sampleThreads();
|
|
||||||
|
|
||||||
return states.get(Thread.State.TIMED_WAITING);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ManagedOperation(value="Number of Waiting Threads", impact="ACTION_INFO")
|
|
||||||
public int getThreadsWaiting()
|
|
||||||
{
|
|
||||||
sampleThreads();
|
|
||||||
|
|
||||||
return states.get(Thread.State.WAITING);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ManagedOperation(value="Number of Runnable Threads", impact="ACTION_INFO")
|
|
||||||
public int getThreadsRunnable()
|
|
||||||
{
|
|
||||||
sampleThreads();
|
|
||||||
|
|
||||||
return states.get(Thread.State.RUNNABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void sampleThreads()
|
|
||||||
{
|
|
||||||
if ((lastSampled + 50L) < System.currentTimeMillis())
|
|
||||||
{
|
|
||||||
lastSampled = System.currentTimeMillis();
|
|
||||||
for (final Thread.State state : Thread.State.values())
|
|
||||||
{
|
|
||||||
states.put(state,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final ThreadInfo thread : threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds()))
|
|
||||||
{
|
|
||||||
if (thread != null)
|
|
||||||
{
|
|
||||||
final Thread.State state = thread.getThreadState();
|
|
||||||
states.put(state,states.get(state) + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
states.put(Thread.State.TERMINATED,states.get(Thread.State.TERMINATED) + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String POLICY = "sun.net.InetAddressCachePolicy";
|
|
||||||
|
|
||||||
@ManagedOperation(value="Amount of time successful DNS queries are cached for.")
|
|
||||||
public int getCacheSeconds() throws ClassNotFoundException,
|
|
||||||
IllegalAccessException, InvocationTargetException,
|
|
||||||
NoSuchMethodException {
|
|
||||||
final Class policy = Class.forName(POLICY);
|
|
||||||
final Object returnValue = policy.getMethod("get", (Class[]) null)
|
|
||||||
.invoke(null, (Object[]) null);
|
|
||||||
Integer seconds = (Integer) returnValue;
|
|
||||||
|
|
||||||
return seconds.intValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@ManagedOperation(value="Amount of time failed DNS queries are cached for")
|
|
||||||
public int getCacheNegativeSeconds() throws ClassNotFoundException,
|
|
||||||
IllegalAccessException, InvocationTargetException,
|
|
||||||
NoSuchMethodException {
|
|
||||||
final Class policy = Class.forName(POLICY);
|
|
||||||
final Object returnValue = policy.getMethod("getNegative",
|
|
||||||
(Class[]) null).invoke(null, (Object[]) null);
|
|
||||||
Integer seconds = (Integer) returnValue;
|
|
||||||
|
|
||||||
return seconds.intValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String DEFAULT = "default";
|
|
||||||
|
|
||||||
private static final String SECURITY = "security";
|
|
||||||
|
|
||||||
private static final String SYSTEM = "system";
|
|
||||||
|
|
||||||
private static final String BOTH = "both";
|
|
||||||
|
|
||||||
private static final String SECURITY_TTL = "networkaddress.cache.ttl";
|
|
||||||
|
|
||||||
private static final String SYSTEM_TTL = "sun.net.inetaddr.ttl";
|
|
||||||
|
|
||||||
private static final String SECURITY_NEGATIVE_TTL = "networkaddress.cache.negative.ttl";
|
|
||||||
|
|
||||||
private static final String SYSTEM_NEGATIVE_TTL = "sun.net.inetaddr.negative.ttl";
|
|
||||||
|
|
||||||
@ManagedOperation(value="Cache policy for successful DNS lookups was changed from the hard-coded default")
|
|
||||||
public String getCacheTweakedFrom() {
|
|
||||||
if (Security.getProperty(SECURITY_TTL) != null) {
|
|
||||||
if (System.getProperty(SYSTEM_TTL) != null) {
|
|
||||||
return BOTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SECURITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (System.getProperty(SYSTEM_TTL) != null) {
|
|
||||||
return SYSTEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ManagedOperation(value="Cache policy for failed DNS lookups was changed from the hard-coded default")
|
|
||||||
public String getCacheNegativeTweakedFrom() {
|
|
||||||
if (Security.getProperty(SECURITY_NEGATIVE_TTL) != null) {
|
|
||||||
if (System.getProperty(SYSTEM_NEGATIVE_TTL) != null) {
|
|
||||||
return BOTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SECURITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (System.getProperty(SYSTEM_NEGATIVE_TTL) != null) {
|
|
||||||
return SYSTEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DEFAULT;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.integration;
|
|
||||||
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.monitor.triggers.AttrEventTrigger;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param <TYPE> the trigger type
|
|
||||||
*/
|
|
||||||
public class JavaMonitorTrigger <TYPE extends Comparable<TYPE>>
|
|
||||||
extends AttrEventTrigger<TYPE>
|
|
||||||
{
|
|
||||||
private final String _id;
|
|
||||||
private final String _name;
|
|
||||||
private final boolean _dynamic;
|
|
||||||
private int _count;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public JavaMonitorTrigger(ObjectName nameObject, String attributeName, String id, String name, boolean dynamic)
|
|
||||||
throws IllegalArgumentException
|
|
||||||
{
|
|
||||||
super(nameObject, attributeName);
|
|
||||||
|
|
||||||
_id = id;
|
|
||||||
_name = name;
|
|
||||||
_dynamic = dynamic;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean match(Comparable<TYPE> value)
|
|
||||||
{
|
|
||||||
return _dynamic ? true : (_count++ < 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean getSaveAll()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getID()
|
|
||||||
{
|
|
||||||
return _id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getNameString()
|
|
||||||
{
|
|
||||||
return _name;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Jetty Monitor : Intregation with Java Monitor
|
|
||||||
*/
|
|
||||||
package org.eclipse.jetty.monitor.integration;
|
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.jmx;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* ConsoleNotifier
|
|
||||||
*
|
|
||||||
* Provides a way to output notification messages to the server console
|
|
||||||
*/
|
|
||||||
public class ConsoleNotifier implements EventNotifier
|
|
||||||
{
|
|
||||||
String _messageFormat;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Constructs a new notifier with specified format string
|
|
||||||
*
|
|
||||||
* @param format the {@link java.util.Formatter format string}
|
|
||||||
* @throws IllegalArgumentException if format is invalid
|
|
||||||
*/
|
|
||||||
public ConsoleNotifier(String format)
|
|
||||||
throws IllegalArgumentException
|
|
||||||
{
|
|
||||||
if (format == null)
|
|
||||||
throw new IllegalArgumentException("Message format cannot be null");
|
|
||||||
|
|
||||||
_messageFormat = format;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.monitor.jmx.EventNotifier#notify(org.eclipse.jetty.monitor.jmx.EventTrigger, org.eclipse.jetty.monitor.jmx.EventState, long)
|
|
||||||
*/
|
|
||||||
public void notify(EventTrigger trigger, EventState<?> state, long timestamp)
|
|
||||||
{
|
|
||||||
String output = String.format("%1$tF %1$tT.%1$tL:NOTIFY::", timestamp);
|
|
||||||
|
|
||||||
output += String.format(_messageFormat, state);
|
|
||||||
|
|
||||||
System.out.println(output);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.jmx;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* EventNotifier
|
|
||||||
*
|
|
||||||
* Interface for classes used to send event notifications
|
|
||||||
*/
|
|
||||||
public interface EventNotifier
|
|
||||||
{
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* This method is called when a notification event is received by the containing object
|
|
||||||
*
|
|
||||||
* @param trigger the event trigger
|
|
||||||
* @param state an {@link org.eclipse.jetty.monitor.jmx.EventState event state}
|
|
||||||
* @param timestamp time stamp of the event
|
|
||||||
*/
|
|
||||||
public void notify(EventTrigger trigger, EventState<?> state, long timestamp);
|
|
||||||
}
|
|
|
@ -1,209 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.jmx;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* EventState
|
|
||||||
*
|
|
||||||
* Holds the state of one or more {@link org.eclipse.jetty.monitor.jmx.EventTrigger event trigger}
|
|
||||||
* instances to be used when sending notifications as well as executing the actions
|
|
||||||
* @param <TYPE> the event trigger type
|
|
||||||
*/
|
|
||||||
public class EventState<TYPE>
|
|
||||||
{
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* State
|
|
||||||
*
|
|
||||||
* Holds the state of a single {@link org.eclipse.jetty.monitor.jmx.EventTrigger event trigger}
|
|
||||||
* @param <TYPE> the event trigger type
|
|
||||||
*/
|
|
||||||
public static class TriggerState<TYPE>
|
|
||||||
{
|
|
||||||
private final String _id;
|
|
||||||
private final String _desc;
|
|
||||||
private final TYPE _value;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct a trigger state
|
|
||||||
*
|
|
||||||
* @param id unique identification string of the associated event trigger
|
|
||||||
* @param desc description of the associated event trigger
|
|
||||||
* @param value effective value of the MXBean attribute (if applicable)
|
|
||||||
*/
|
|
||||||
public TriggerState(String id, String desc, TYPE value)
|
|
||||||
{
|
|
||||||
_id = id;
|
|
||||||
_desc = desc;
|
|
||||||
_value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve the identification string of associated event trigger
|
|
||||||
*
|
|
||||||
* @return unique identification string
|
|
||||||
*/
|
|
||||||
public String getID()
|
|
||||||
{
|
|
||||||
return _id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve the description string set by event trigger
|
|
||||||
*
|
|
||||||
* @return description string
|
|
||||||
*/
|
|
||||||
public String getDescription()
|
|
||||||
{
|
|
||||||
return _desc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve the effective value of the MXBean attribute (if applicable)
|
|
||||||
*
|
|
||||||
* @return attribute value
|
|
||||||
*/
|
|
||||||
public TYPE getValue()
|
|
||||||
{
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @return string representation of the state
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
result.append(_desc);
|
|
||||||
result.append('=');
|
|
||||||
result.append(_value);
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Map<String, TriggerState<TYPE>> _states;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Constructs an empty event state
|
|
||||||
*/
|
|
||||||
public EventState()
|
|
||||||
{
|
|
||||||
_states = new ConcurrentHashMap<String, TriggerState<TYPE>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Constructs an event state and adds a specified trigger state to it
|
|
||||||
*
|
|
||||||
* @param id unique identification string of the associated event trigger
|
|
||||||
* @param desc description of the associated event trigger
|
|
||||||
* @param value effective value of the MXBean attribute (if applicable)
|
|
||||||
*/
|
|
||||||
public EventState(String id, String desc, TYPE value)
|
|
||||||
{
|
|
||||||
this();
|
|
||||||
|
|
||||||
add(new TriggerState<TYPE>(id, desc, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Adds a trigger state to the event state
|
|
||||||
*
|
|
||||||
* @param state trigger state to add
|
|
||||||
*/
|
|
||||||
public void add(TriggerState<TYPE> state)
|
|
||||||
{
|
|
||||||
_states.put(state.getID(), state);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Adds a collection of trigger states to the event state
|
|
||||||
*
|
|
||||||
* @param entries collection of trigger states to add
|
|
||||||
*/
|
|
||||||
public void addAll(Collection<TriggerState<TYPE>> entries)
|
|
||||||
{
|
|
||||||
for (TriggerState<TYPE> entry : entries)
|
|
||||||
{
|
|
||||||
add(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieves a single trigger state
|
|
||||||
*
|
|
||||||
* @param id unique identification string of the event trigger
|
|
||||||
* @return requested trigger state or null if not found
|
|
||||||
*/
|
|
||||||
public TriggerState<TYPE> get(String id)
|
|
||||||
{
|
|
||||||
return _states.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieves a collection of all trigger states of the event state
|
|
||||||
*
|
|
||||||
* @return collection of the trigger states
|
|
||||||
*/
|
|
||||||
public Collection<TriggerState<TYPE>> values()
|
|
||||||
{
|
|
||||||
return Collections.unmodifiableCollection(_states.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Returns a string representation of the event state
|
|
||||||
*
|
|
||||||
* @return string representation of the event state
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
int cnt = 0;
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
for (TriggerState<TYPE> value : _states.values())
|
|
||||||
{
|
|
||||||
result.append(cnt++>0?"#":"");
|
|
||||||
result.append(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.jmx;
|
|
||||||
|
|
||||||
import static java.util.UUID.randomUUID;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* EventTrigger
|
|
||||||
*
|
|
||||||
* Abstract base class for all EventTrigger implementations.
|
|
||||||
* Used to determine whether the necessary conditions for
|
|
||||||
* triggering an event are present.
|
|
||||||
*/
|
|
||||||
public abstract class EventTrigger
|
|
||||||
{
|
|
||||||
private final String _id;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct an event trigger
|
|
||||||
*/
|
|
||||||
public EventTrigger()
|
|
||||||
{
|
|
||||||
_id = randomUUID().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve the identification string of the event trigger
|
|
||||||
*
|
|
||||||
* @return unique identification string
|
|
||||||
*/
|
|
||||||
public String getID()
|
|
||||||
{
|
|
||||||
return _id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Abstract method to verify if the event trigger conditions
|
|
||||||
* are in the appropriate state for an event to be triggered
|
|
||||||
*
|
|
||||||
* @param timestamp the timestamp to match
|
|
||||||
* @return true to trigger an event
|
|
||||||
* @throws Exception if unable to match
|
|
||||||
*/
|
|
||||||
public abstract boolean match(long timestamp) throws Exception;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve the event state associated with specified invocation
|
|
||||||
* of the event trigger match method
|
|
||||||
*
|
|
||||||
* @param timestamp time stamp associated with invocation
|
|
||||||
* @return event state or null if not found
|
|
||||||
*/
|
|
||||||
public abstract EventState<?> getState(long timestamp);
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.jmx;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* ConsoleNotifier
|
|
||||||
*
|
|
||||||
* Provides a way to output notification messages to a log file
|
|
||||||
*/
|
|
||||||
public class LoggingNotifier implements EventNotifier
|
|
||||||
{
|
|
||||||
private static final Logger LOG = Log.getLogger(LoggingNotifier.class);
|
|
||||||
|
|
||||||
String _messageFormat;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Constructs a new notifier with specified format string
|
|
||||||
*
|
|
||||||
* @param format the {@link java.util.Formatter format string}
|
|
||||||
* @throws IllegalArgumentException if format is invalid
|
|
||||||
*/
|
|
||||||
public LoggingNotifier(String format)
|
|
||||||
throws IllegalArgumentException
|
|
||||||
{
|
|
||||||
if (format == null)
|
|
||||||
throw new IllegalArgumentException("Message format cannot be null");
|
|
||||||
|
|
||||||
_messageFormat = format;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.monitor.jmx.EventNotifier#notify(org.eclipse.jetty.monitor.jmx.EventTrigger, org.eclipse.jetty.monitor.jmx.EventState, long)
|
|
||||||
*/
|
|
||||||
public void notify(EventTrigger trigger, EventState<?> state, long timestamp)
|
|
||||||
{
|
|
||||||
String output = String.format(_messageFormat, state);
|
|
||||||
|
|
||||||
LOG.info(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,179 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.jmx;
|
|
||||||
|
|
||||||
import static java.util.UUID.randomUUID;
|
|
||||||
|
|
||||||
import java.security.InvalidParameterException;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* MonitorAction
|
|
||||||
*
|
|
||||||
* Abstract base class for all MonitorAction implementations.
|
|
||||||
* Receives notification when an associated EventTrigger is matched.
|
|
||||||
*/
|
|
||||||
public abstract class MonitorAction
|
|
||||||
extends NotifierGroup
|
|
||||||
{
|
|
||||||
public static final int DEFAULT_POLL_INTERVAL = 5000;
|
|
||||||
|
|
||||||
private final String _id;
|
|
||||||
private final EventTrigger _trigger;
|
|
||||||
private final EventNotifier _notifier;
|
|
||||||
private final long _pollInterval;
|
|
||||||
private final long _pollDelay;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Creates a new monitor action
|
|
||||||
*
|
|
||||||
* @param trigger event trigger to be associated with this action
|
|
||||||
* @throws InvalidParameterException if trigger is invalid
|
|
||||||
*/
|
|
||||||
public MonitorAction(EventTrigger trigger)
|
|
||||||
throws InvalidParameterException
|
|
||||||
{
|
|
||||||
this(trigger, null, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Creates a new monitor action
|
|
||||||
*
|
|
||||||
* @param trigger event trigger to be associated with this action
|
|
||||||
* @param notifier event notifier to be associated with this action
|
|
||||||
* @throws InvalidParameterException if trigger is invalid
|
|
||||||
*/
|
|
||||||
public MonitorAction(EventTrigger trigger, EventNotifier notifier)
|
|
||||||
throws InvalidParameterException
|
|
||||||
{
|
|
||||||
this(trigger, notifier, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Creates a new monitor action
|
|
||||||
*
|
|
||||||
* @param trigger event trigger to be associated with this action
|
|
||||||
* @param notifier event notifier to be associated with this action
|
|
||||||
* @param pollInterval interval for polling of the JMX server
|
|
||||||
* @throws InvalidParameterException if trigger is invalid
|
|
||||||
*/
|
|
||||||
public MonitorAction(EventTrigger trigger, EventNotifier notifier, long pollInterval)
|
|
||||||
throws InvalidParameterException
|
|
||||||
{
|
|
||||||
this(trigger, notifier, pollInterval, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Creates a new monitor action
|
|
||||||
*
|
|
||||||
* @param trigger event trigger to be associated with this action
|
|
||||||
* @param notifier event notifier to be associated with this action
|
|
||||||
* @param pollInterval interval for polling of the JMX server
|
|
||||||
* @param pollDelay delay before starting to poll the JMX server
|
|
||||||
* @throws InvalidParameterException if trigger is invalid
|
|
||||||
*/
|
|
||||||
public MonitorAction(EventTrigger trigger, EventNotifier notifier, long pollInterval, long pollDelay)
|
|
||||||
throws InvalidParameterException
|
|
||||||
{
|
|
||||||
if (trigger == null)
|
|
||||||
throw new InvalidParameterException("Trigger cannot be null");
|
|
||||||
|
|
||||||
_id = randomUUID().toString();
|
|
||||||
_trigger = trigger;
|
|
||||||
_notifier = notifier;
|
|
||||||
_pollInterval = pollInterval > 0 ? pollInterval : DEFAULT_POLL_INTERVAL;
|
|
||||||
_pollDelay = pollDelay > 0 ? pollDelay : _pollInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve the identification string of the monitor action
|
|
||||||
*
|
|
||||||
* @return unique identification string
|
|
||||||
*/
|
|
||||||
|
|
||||||
public final String getID()
|
|
||||||
{
|
|
||||||
return _id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve the event trigger of the monitor action
|
|
||||||
*
|
|
||||||
* @return associated event trigger
|
|
||||||
*/
|
|
||||||
public EventTrigger getTrigger()
|
|
||||||
{
|
|
||||||
return _trigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve the poll interval
|
|
||||||
*
|
|
||||||
* @return interval value (in milliseconds)
|
|
||||||
*/
|
|
||||||
public long getPollInterval()
|
|
||||||
{
|
|
||||||
return _pollInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/** Retrieve the poll delay
|
|
||||||
* @return delay value (in milliseconds)
|
|
||||||
*/
|
|
||||||
public long getPollDelay()
|
|
||||||
{
|
|
||||||
return _pollDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* This method will be called when event trigger associated
|
|
||||||
* with this monitor action matches its conditions.
|
|
||||||
*
|
|
||||||
* @param timestamp time stamp of the event
|
|
||||||
*/
|
|
||||||
public final void doExecute(long timestamp)
|
|
||||||
{
|
|
||||||
EventState<?> state =_trigger.getState(timestamp);
|
|
||||||
if (_notifier != null)
|
|
||||||
_notifier.notify(_trigger, state, timestamp);
|
|
||||||
execute(_trigger, state, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* This method will be called to allow subclass to execute
|
|
||||||
* the desired action in response to the event.
|
|
||||||
*
|
|
||||||
* @param trigger event trigger associated with this monitor action
|
|
||||||
* @param state event state associated with current invocation of event trigger
|
|
||||||
* @param timestamp time stamp of the current invocation of event trigger
|
|
||||||
*/
|
|
||||||
public abstract void execute(EventTrigger trigger, EventState<?> state, long timestamp);
|
|
||||||
}
|
|
|
@ -1,119 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.jmx;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
|
||||||
import org.eclipse.jetty.util.thread.ExecutorThreadPool;
|
|
||||||
import org.eclipse.jetty.util.thread.ThreadPool;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* MonitorTask
|
|
||||||
*
|
|
||||||
* Invokes polling of the JMX server for the MBean attribute values
|
|
||||||
* through executing timer task scheduled using java.util.Timer
|
|
||||||
* at specified poll interval following a specified delay.
|
|
||||||
*/
|
|
||||||
public class MonitorTask extends TimerTask
|
|
||||||
{
|
|
||||||
private static final Logger LOG = Log.getLogger(MonitorTask.class);
|
|
||||||
|
|
||||||
private static Timer __timer = new Timer(true);
|
|
||||||
private static ThreadPool _callback = new ExecutorThreadPool(4,64,60,TimeUnit.SECONDS);;
|
|
||||||
private static Map<String,TimerTask> __tasks = new HashMap<String,TimerTask>();
|
|
||||||
|
|
||||||
private final MonitorAction _action;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Creates new instance of MonitorTask
|
|
||||||
*
|
|
||||||
* @param action instance of MonitorAction to use
|
|
||||||
*/
|
|
||||||
private MonitorTask(MonitorAction action)
|
|
||||||
{
|
|
||||||
_action = action;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Schedule new timer task for specified monitor action
|
|
||||||
*
|
|
||||||
* @param action monitor action
|
|
||||||
*/
|
|
||||||
public static void schedule(MonitorAction action)
|
|
||||||
{
|
|
||||||
TimerTask task = new MonitorTask(action);
|
|
||||||
__timer.scheduleAtFixedRate(task,
|
|
||||||
action.getPollDelay(),
|
|
||||||
action.getPollInterval());
|
|
||||||
|
|
||||||
__tasks.put(action.getID(), task);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Cancel timer task for specified monitor action
|
|
||||||
*
|
|
||||||
* @param action monitor action
|
|
||||||
*/
|
|
||||||
public static void cancel(MonitorAction action)
|
|
||||||
{
|
|
||||||
TimerTask task = __tasks.remove(action.getID());
|
|
||||||
if (task != null)
|
|
||||||
task.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* This method is invoked when poll interval has elapsed
|
|
||||||
* to check if the event trigger conditions are satisfied
|
|
||||||
* in order to fire event.
|
|
||||||
*
|
|
||||||
* @see java.util.TimerTask#run()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final void run()
|
|
||||||
{
|
|
||||||
final long timestamp = System.currentTimeMillis();
|
|
||||||
final EventTrigger trigger = _action.getTrigger();
|
|
||||||
|
|
||||||
_callback.execute(new Runnable() {
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if(trigger.match(timestamp))
|
|
||||||
_action.doExecute(timestamp);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
LOG.debug(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,119 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.jmx;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* NotifierGroup
|
|
||||||
*
|
|
||||||
* This class allows for grouping of the event notifiers
|
|
||||||
*/
|
|
||||||
public class NotifierGroup implements EventNotifier
|
|
||||||
{
|
|
||||||
private Set<EventNotifier> _group;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Create a notifier group
|
|
||||||
*/
|
|
||||||
public NotifierGroup()
|
|
||||||
{
|
|
||||||
_group = new HashSet<EventNotifier>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve all event notifier associated with this group
|
|
||||||
*
|
|
||||||
* @return collection of event notifiers
|
|
||||||
*/
|
|
||||||
public Collection<EventNotifier> getNotifiers()
|
|
||||||
{
|
|
||||||
return Collections.unmodifiableSet(_group);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Add specified event notifier to event notifier group
|
|
||||||
*
|
|
||||||
* @param notifier event notifier to be added
|
|
||||||
* @return true if successful
|
|
||||||
*/
|
|
||||||
public boolean addNotifier(EventNotifier notifier)
|
|
||||||
{
|
|
||||||
return _group.add(notifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Add a collection of event notifiers to event notifier group
|
|
||||||
*
|
|
||||||
* @param notifiers collection of event notifiers to be added
|
|
||||||
* @return true if successful
|
|
||||||
*/
|
|
||||||
public boolean addNotifiers(Collection<EventNotifier> notifiers)
|
|
||||||
{
|
|
||||||
return _group.addAll(notifiers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Remove event notifier from event notifier group
|
|
||||||
*
|
|
||||||
* @param notifier event notifier to be removed
|
|
||||||
* @return true if successful
|
|
||||||
*/
|
|
||||||
public boolean removeNotifier(EventNotifier notifier)
|
|
||||||
{
|
|
||||||
return _group.remove(notifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Remove a collection of event notifiers from event notifier group
|
|
||||||
*
|
|
||||||
* @param notifiers collection of event notifiers to be removed
|
|
||||||
* @return true if successful
|
|
||||||
*/
|
|
||||||
public boolean removeNotifiers(Collection<EventNotifier> notifiers)
|
|
||||||
{
|
|
||||||
return _group.removeAll(notifiers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Invoke the notify() method of each of the notifiers in group
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.jmx.EventNotifier#notify(org.eclipse.jetty.monitor.jmx.EventTrigger, org.eclipse.jetty.monitor.jmx.EventState, long)
|
|
||||||
*/
|
|
||||||
public void notify(EventTrigger trigger, EventState<?> state, long timestamp)
|
|
||||||
{
|
|
||||||
for (EventNotifier notifier: _group)
|
|
||||||
{
|
|
||||||
notifier.notify(trigger, state, timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,172 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.jmx;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
|
|
||||||
import javax.management.MBeanServer;
|
|
||||||
import javax.management.MBeanServerConnection;
|
|
||||||
import javax.management.remote.JMXConnector;
|
|
||||||
import javax.management.remote.JMXConnectorFactory;
|
|
||||||
import javax.management.remote.JMXConnectorServer;
|
|
||||||
import javax.management.remote.JMXConnectorServerFactory;
|
|
||||||
import javax.management.remote.JMXServiceURL;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* ServerConnection
|
|
||||||
*
|
|
||||||
* Provides ability to create a connection to either an external
|
|
||||||
* JMX server, or a loopback connection to the internal one.
|
|
||||||
*/
|
|
||||||
public class ServiceConnection
|
|
||||||
{
|
|
||||||
private static final Logger LOG = Log.getLogger(ServiceConnection.class);
|
|
||||||
|
|
||||||
private String _serviceUrl;
|
|
||||||
private MBeanServer _server;
|
|
||||||
private JMXConnectorServer _connectorServer;
|
|
||||||
private JMXConnector _serverConnector;
|
|
||||||
private MBeanServerConnection _serviceConnection;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct a loopback connection to an internal server
|
|
||||||
*
|
|
||||||
* @throws IOException if unable to construct service connection
|
|
||||||
*/
|
|
||||||
public ServiceConnection()
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct a connection to specified server
|
|
||||||
*
|
|
||||||
* @param url URL of JMX server
|
|
||||||
* @throws IOException if unable to construct service connection
|
|
||||||
*/
|
|
||||||
public ServiceConnection(String url)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
_serviceUrl = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve an external URL for the JMX server
|
|
||||||
*
|
|
||||||
* @return service URL
|
|
||||||
*/
|
|
||||||
public String getServiceUrl()
|
|
||||||
{
|
|
||||||
return _serviceUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve a connection to MBean server
|
|
||||||
*
|
|
||||||
* @return connection to MBean server
|
|
||||||
*/
|
|
||||||
public MBeanServerConnection getConnection()
|
|
||||||
{
|
|
||||||
return _serviceConnection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void connect()
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
if (_serviceConnection == null)
|
|
||||||
{
|
|
||||||
if (_serviceUrl == null)
|
|
||||||
openLoopbackConnection();
|
|
||||||
else
|
|
||||||
openServerConnection(_serviceUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Open a loopback connection to local JMX server
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private void openLoopbackConnection()
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
_server = ManagementFactory.getPlatformMBeanServer();
|
|
||||||
|
|
||||||
JMXServiceURL serviceUrl = new JMXServiceURL("service:jmx:rmi://");
|
|
||||||
_connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(serviceUrl, null, _server);
|
|
||||||
_connectorServer.start();
|
|
||||||
|
|
||||||
_serviceUrl = _connectorServer.getAddress().toString();
|
|
||||||
|
|
||||||
_serverConnector = JMXConnectorFactory.connect(_connectorServer.getAddress());
|
|
||||||
_serviceConnection = _serverConnector.getMBeanServerConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Open a connection to remote JMX server
|
|
||||||
*
|
|
||||||
* @param url
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private void openServerConnection(String url)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
_serviceUrl = url;
|
|
||||||
|
|
||||||
JMXServiceURL serviceUrl = new JMXServiceURL(_serviceUrl);
|
|
||||||
_serverConnector = JMXConnectorFactory.connect(serviceUrl);
|
|
||||||
_serviceConnection = _serverConnector.getMBeanServerConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Close the connections
|
|
||||||
*/
|
|
||||||
public void disconnect()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_serverConnector != null)
|
|
||||||
{
|
|
||||||
_serverConnector.close();
|
|
||||||
_serviceConnection = null;
|
|
||||||
}
|
|
||||||
if (_connectorServer != null)
|
|
||||||
{
|
|
||||||
_connectorServer.stop();
|
|
||||||
_connectorServer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
LOG.debug(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.jmx;
|
|
||||||
|
|
||||||
import java.security.InvalidParameterException;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
public class SimpleAction extends MonitorAction
|
|
||||||
{
|
|
||||||
public SimpleAction(EventTrigger trigger, EventNotifier notifier, long pollInterval)
|
|
||||||
throws InvalidParameterException
|
|
||||||
{
|
|
||||||
super(trigger,notifier,pollInterval);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.monitor.jmx.MonitorAction#execute(org.eclipse.jetty.monitor.jmx.EventTrigger, org.eclipse.jetty.monitor.jmx.EventState, long)
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(EventTrigger trigger, EventState<?> state, long timestamp)
|
|
||||||
{
|
|
||||||
System.out.printf("Action time: %tc%n", timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Jetty Monitor : JMX Integration
|
|
||||||
*/
|
|
||||||
package org.eclipse.jetty.monitor.jmx;
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Jetty Monitor : Tool for Monitoring Threads
|
|
||||||
*/
|
|
||||||
package org.eclipse.jetty.monitor;
|
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.thread;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
public class ThreadMonitorException extends Exception
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = -4345223166315716918L;
|
|
||||||
|
|
||||||
public ThreadMonitorException(String message, StackTraceElement[] stackTrace)
|
|
||||||
{
|
|
||||||
super(message);
|
|
||||||
setStackTrace(stackTrace);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,202 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.thread;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
public class ThreadMonitorInfo
|
|
||||||
{
|
|
||||||
private Thread _thread;
|
|
||||||
private StackTraceElement[] _stackTrace;
|
|
||||||
|
|
||||||
private boolean _threadSpinning = false;
|
|
||||||
private int _traceCount = -1;
|
|
||||||
|
|
||||||
private long _prevCpuTime;
|
|
||||||
private long _prevSampleTime;
|
|
||||||
private long _currCpuTime;
|
|
||||||
private long _currSampleTime;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Instantiates a new thread monitor info.
|
|
||||||
*
|
|
||||||
* @param thread the thread this object is created for
|
|
||||||
*/
|
|
||||||
public ThreadMonitorInfo(Thread thread)
|
|
||||||
{
|
|
||||||
_thread = thread;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @return Id of the thread
|
|
||||||
*/
|
|
||||||
public long getThreadId()
|
|
||||||
{
|
|
||||||
return _thread.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Gets the thread name.
|
|
||||||
*
|
|
||||||
* @return the thread name
|
|
||||||
*/
|
|
||||||
public String getThreadName()
|
|
||||||
{
|
|
||||||
return _thread.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Gets the thread state.
|
|
||||||
*
|
|
||||||
* @return the thread state
|
|
||||||
*/
|
|
||||||
public String getThreadState()
|
|
||||||
{
|
|
||||||
return _thread.getState().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Gets the stack trace.
|
|
||||||
*
|
|
||||||
* @return the stack trace
|
|
||||||
*/
|
|
||||||
public StackTraceElement[] getStackTrace()
|
|
||||||
{
|
|
||||||
return _stackTrace;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Sets the stack trace.
|
|
||||||
*
|
|
||||||
* @param stackTrace the new stack trace
|
|
||||||
*/
|
|
||||||
public void setStackTrace(StackTraceElement[] stackTrace)
|
|
||||||
{
|
|
||||||
_stackTrace = stackTrace;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Checks if is spinning.
|
|
||||||
*
|
|
||||||
* @return true, if is spinning
|
|
||||||
*/
|
|
||||||
public boolean isSpinning()
|
|
||||||
{
|
|
||||||
return _threadSpinning;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Sets the spinning flag.
|
|
||||||
*
|
|
||||||
* @param value the new value
|
|
||||||
*/
|
|
||||||
public void setSpinning(boolean value)
|
|
||||||
{
|
|
||||||
_threadSpinning = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Sets the trace count.
|
|
||||||
*
|
|
||||||
* @param traceCount the new trace count
|
|
||||||
*/
|
|
||||||
public void setTraceCount(int traceCount)
|
|
||||||
{
|
|
||||||
_traceCount = traceCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Gets the trace count.
|
|
||||||
*
|
|
||||||
* @return the trace count
|
|
||||||
*/
|
|
||||||
public int getTraceCount()
|
|
||||||
{
|
|
||||||
return _traceCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @return the CPU time of the thread
|
|
||||||
*/
|
|
||||||
public long getCpuTime()
|
|
||||||
{
|
|
||||||
return _currCpuTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Set the CPU time.
|
|
||||||
*
|
|
||||||
* @param ns new CPU time
|
|
||||||
*/
|
|
||||||
public void setCpuTime(long ns)
|
|
||||||
{
|
|
||||||
_prevCpuTime = _currCpuTime;
|
|
||||||
_currCpuTime = ns;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @return the time of sample
|
|
||||||
*/
|
|
||||||
public long getSampleTime()
|
|
||||||
{
|
|
||||||
return _currSampleTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Sets the sample time.
|
|
||||||
*
|
|
||||||
* @param ns the time of sample
|
|
||||||
*/
|
|
||||||
public void setSampleTime(long ns)
|
|
||||||
{
|
|
||||||
_prevSampleTime = _currSampleTime;
|
|
||||||
_currSampleTime = ns;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Gets the CPU utilization.
|
|
||||||
*
|
|
||||||
* @return the CPU utilization percentage
|
|
||||||
*/
|
|
||||||
public float getCpuUtilization()
|
|
||||||
{
|
|
||||||
long elapsedCpuTime = _currCpuTime - _prevCpuTime;
|
|
||||||
long elapsedNanoTime = _currSampleTime - _prevSampleTime;
|
|
||||||
|
|
||||||
return elapsedNanoTime > 0 ? Math.min((elapsedCpuTime * 100.0f) / elapsedNanoTime, 100.0f) : 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Jetty Monitor : Thread Monitoring
|
|
||||||
*/
|
|
||||||
package org.eclipse.jetty.monitor.thread;
|
|
||||||
|
|
|
@ -1,159 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.triggers;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventState;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventTrigger;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* AggregateEventTrigger
|
|
||||||
*
|
|
||||||
* EventTrigger aggregation that executes every aggregated event
|
|
||||||
* triggers in left to right order, and returns match if any one
|
|
||||||
* of them have returned match.
|
|
||||||
*/
|
|
||||||
public class AggregateEventTrigger extends EventTrigger
|
|
||||||
{
|
|
||||||
protected final List<EventTrigger> _triggers;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct an event trigger
|
|
||||||
*/
|
|
||||||
public AggregateEventTrigger()
|
|
||||||
{
|
|
||||||
_triggers = new ArrayList<EventTrigger>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct an event trigger and associate the list
|
|
||||||
* of event triggers to be aggregated by this trigger
|
|
||||||
*
|
|
||||||
* @param triggers list of event triggers to add
|
|
||||||
*/
|
|
||||||
public AggregateEventTrigger(List<EventTrigger> triggers)
|
|
||||||
{
|
|
||||||
_triggers = new ArrayList<EventTrigger>(triggers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct an event trigger and associate the array
|
|
||||||
* of event triggers to be aggregated by this trigger
|
|
||||||
*
|
|
||||||
* @param triggers list of event triggers to add
|
|
||||||
*/
|
|
||||||
public AggregateEventTrigger(EventTrigger... triggers)
|
|
||||||
{
|
|
||||||
_triggers = Arrays.asList(triggers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void add(EventTrigger trigger)
|
|
||||||
{
|
|
||||||
_triggers.add(trigger);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void addAll(List<EventTrigger> triggers)
|
|
||||||
{
|
|
||||||
_triggers.addAll(triggers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void addAll(EventTrigger... triggers)
|
|
||||||
{
|
|
||||||
_triggers.addAll(Arrays.asList(triggers));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve the event state associated with specified invocation
|
|
||||||
* of the event trigger match method. This event trigger retrieves
|
|
||||||
* the combined event state of all aggregated event triggers.
|
|
||||||
*
|
|
||||||
* @param timestamp time stamp associated with invocation
|
|
||||||
* @return event state or null if not found
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.jmx.EventTrigger#getState(long)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public EventState getState(long timestamp)
|
|
||||||
{
|
|
||||||
EventState state = new EventState();
|
|
||||||
|
|
||||||
for (EventTrigger trigger : _triggers)
|
|
||||||
{
|
|
||||||
EventState subState = trigger.getState(timestamp);
|
|
||||||
if (subState != null)
|
|
||||||
{
|
|
||||||
state.addAll(subState.values());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.monitor.jmx.EventTrigger#match(long)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean match(long timestamp) throws Exception
|
|
||||||
{
|
|
||||||
boolean result = false;
|
|
||||||
for(EventTrigger trigger : _triggers)
|
|
||||||
{
|
|
||||||
result = trigger.match(timestamp) ? true : result;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Returns the string representation of this event trigger
|
|
||||||
* in the format "AND(triger1,trigger2,...)".
|
|
||||||
*
|
|
||||||
* @return string representation of the event trigger
|
|
||||||
*
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
int cnt = 0;
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
result.append("ANY(");
|
|
||||||
for (EventTrigger trigger : _triggers)
|
|
||||||
{
|
|
||||||
result.append(cnt++ > 0 ? "," : "");
|
|
||||||
result.append(trigger);
|
|
||||||
}
|
|
||||||
result.append(')');
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,134 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.triggers;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventState;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventTrigger;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* AndEventTrigger
|
|
||||||
*
|
|
||||||
* EventTrigger aggregation using logical AND operation
|
|
||||||
* that executes matching of the aggregated event triggers
|
|
||||||
* in left to right order
|
|
||||||
*/
|
|
||||||
public class AndEventTrigger extends EventTrigger
|
|
||||||
{
|
|
||||||
protected final List<EventTrigger> _triggers;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct an event trigger and associate the list
|
|
||||||
* of event triggers to be aggregated by this trigger
|
|
||||||
*
|
|
||||||
* @param triggers list of event triggers to add
|
|
||||||
*/
|
|
||||||
public AndEventTrigger(List<EventTrigger> triggers)
|
|
||||||
{
|
|
||||||
_triggers = triggers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct an event trigger and associate the array
|
|
||||||
* of event triggers to be aggregated by this trigger
|
|
||||||
*
|
|
||||||
* @param triggers array of event triggers to add
|
|
||||||
*/
|
|
||||||
public AndEventTrigger(EventTrigger... triggers)
|
|
||||||
{
|
|
||||||
_triggers = Arrays.asList(triggers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Verify if the event trigger conditions are in the
|
|
||||||
* appropriate state for an event to be triggered.
|
|
||||||
* This event trigger will match if all aggregated
|
|
||||||
* event triggers would return a match.
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.jmx.EventTrigger#match(long)
|
|
||||||
*/
|
|
||||||
public boolean match(long timestamp)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
for(EventTrigger trigger : _triggers)
|
|
||||||
{
|
|
||||||
if (!trigger.match(timestamp))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve the event state associated with specified invocation
|
|
||||||
* of the event trigger match method. This event trigger retrieves
|
|
||||||
* the combined event state of all aggregated event triggers.
|
|
||||||
*
|
|
||||||
* @param timestamp time stamp associated with invocation
|
|
||||||
* @return event state or null if not found
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.jmx.EventTrigger#getState(long)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public EventState getState(long timestamp)
|
|
||||||
{
|
|
||||||
EventState state = new EventState();
|
|
||||||
|
|
||||||
for (EventTrigger trigger : _triggers)
|
|
||||||
{
|
|
||||||
EventState subState = trigger.getState(timestamp);
|
|
||||||
state.addAll(subState.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Returns the string representation of this event trigger
|
|
||||||
* in the format "AND(triger1,trigger2,...)".
|
|
||||||
*
|
|
||||||
* @return string representation of the event trigger
|
|
||||||
*
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
int cnt = 0;
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
result.append("AND(");
|
|
||||||
for (EventTrigger trigger : _triggers)
|
|
||||||
{
|
|
||||||
result.append(cnt++ > 0 ? "," : "");
|
|
||||||
result.append(trigger);
|
|
||||||
}
|
|
||||||
result.append(')');
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,240 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.triggers;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import javax.management.MBeanServerConnection;
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
import javax.management.openmbean.CompositeData;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.monitor.JMXMonitor;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventState;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventTrigger;
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AttrEventTrigger
|
|
||||||
* <p>
|
|
||||||
* Event trigger that polls a value of an MXBean attribute
|
|
||||||
* and matches every invocation of this trigger. It can be
|
|
||||||
* used to send notifications of the value of an attribute
|
|
||||||
* of the MXBean being polled at a certain interval, or as
|
|
||||||
* a base class for the event triggers that match the
|
|
||||||
* value of an attribute of the MXBean being polled against
|
|
||||||
* some specified criteria.
|
|
||||||
* @param <TYPE> the event trigger type
|
|
||||||
*/
|
|
||||||
public class AttrEventTrigger<TYPE extends Comparable<TYPE>>
|
|
||||||
extends EventTrigger
|
|
||||||
{
|
|
||||||
private static final Logger LOG = Log.getLogger(AttrEventTrigger.class);
|
|
||||||
|
|
||||||
private final ObjectName _nameObject;
|
|
||||||
|
|
||||||
protected final String _objectName;
|
|
||||||
protected final String _attributeName;
|
|
||||||
protected Map<Long, EventState<TYPE>> _states;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct event trigger and specify the MXBean attribute
|
|
||||||
* that will be polled by this event trigger.
|
|
||||||
*
|
|
||||||
* @param objectName object name of an MBean to be polled
|
|
||||||
* @param attributeName name of an MBean attribute to be polled
|
|
||||||
*
|
|
||||||
* @throws MalformedObjectNameException if unable to find object due to malformed name reference
|
|
||||||
* @throws IllegalArgumentException if parameters are invalid
|
|
||||||
*/
|
|
||||||
public AttrEventTrigger(String objectName, String attributeName)
|
|
||||||
throws MalformedObjectNameException, IllegalArgumentException
|
|
||||||
{
|
|
||||||
if (objectName == null)
|
|
||||||
throw new IllegalArgumentException("Object name cannot be null");
|
|
||||||
if (attributeName == null)
|
|
||||||
throw new IllegalArgumentException("Attribute name cannot be null");
|
|
||||||
|
|
||||||
_states = new ConcurrentHashMap<Long,EventState<TYPE>>();
|
|
||||||
|
|
||||||
_objectName = objectName;
|
|
||||||
_attributeName = attributeName;
|
|
||||||
|
|
||||||
_nameObject = new ObjectName(_objectName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct event trigger and specify the MXBean attribute
|
|
||||||
* that will be polled by this event trigger.
|
|
||||||
*
|
|
||||||
* @param nameObject object name of an MBean to be polled
|
|
||||||
* @param attributeName name of an MBean attribute to be polled
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException if parameters are invalid
|
|
||||||
*/
|
|
||||||
public AttrEventTrigger(ObjectName nameObject, String attributeName)
|
|
||||||
throws IllegalArgumentException
|
|
||||||
{
|
|
||||||
if (nameObject == null)
|
|
||||||
throw new IllegalArgumentException("Object name cannot be null");
|
|
||||||
if (attributeName == null)
|
|
||||||
throw new IllegalArgumentException("Attribute name cannot be null");
|
|
||||||
|
|
||||||
_states = new ConcurrentHashMap<Long,EventState<TYPE>>();
|
|
||||||
|
|
||||||
_objectName = nameObject.toString();
|
|
||||||
_attributeName = attributeName;
|
|
||||||
|
|
||||||
_nameObject = nameObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Verify if the event trigger conditions are in the
|
|
||||||
* appropriate state for an event to be triggered.
|
|
||||||
* This event trigger uses the match(Comparable<TYPE>)
|
|
||||||
* method to compare the value of the MXBean attribute
|
|
||||||
* to the conditions specified by the subclasses.
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.jmx.EventTrigger#match(long)
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final boolean match(long timestamp)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
MBeanServerConnection serverConnection = JMXMonitor.getServiceConnection();
|
|
||||||
|
|
||||||
TYPE value = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int pos = _attributeName.indexOf('.');
|
|
||||||
if (pos < 0)
|
|
||||||
value = (TYPE)serverConnection.getAttribute(_nameObject,_attributeName);
|
|
||||||
else
|
|
||||||
value = getValue((CompositeData)serverConnection.getAttribute(_nameObject, _attributeName.substring(0, pos)),
|
|
||||||
_attributeName.substring(pos+1));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
LOG.debug(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean result = false;
|
|
||||||
if (value != null)
|
|
||||||
{
|
|
||||||
result = match(value);
|
|
||||||
|
|
||||||
if (result || getSaveAll())
|
|
||||||
{
|
|
||||||
_states.put(timestamp,
|
|
||||||
new EventState<TYPE>(this.getID(), this.getNameString(), value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Verify if the event trigger conditions are in the
|
|
||||||
* appropriate state for an event to be triggered.
|
|
||||||
* Allows subclasses to override the default behavior
|
|
||||||
* that matches every invocation of this trigger
|
|
||||||
* @param value the value to match
|
|
||||||
* @return always true
|
|
||||||
*/
|
|
||||||
public boolean match(Comparable<TYPE> value)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve the event state associated with specified invocation
|
|
||||||
* of the event trigger match method.
|
|
||||||
*
|
|
||||||
* @param timestamp time stamp associated with invocation
|
|
||||||
* @return event state or null if not found
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.jmx.EventTrigger#getState(long)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final EventState<TYPE> getState(long timestamp)
|
|
||||||
{
|
|
||||||
return _states.get(timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Returns the string representation of this event trigger
|
|
||||||
* in the format "[object_name:attribute_name]".
|
|
||||||
*
|
|
||||||
* @return string representation of the event trigger
|
|
||||||
*
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return getNameString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Returns the string representation of this event trigger
|
|
||||||
* in the format "[object_name:attribute_name]". Allows
|
|
||||||
* subclasses to override the name string used to identify
|
|
||||||
* this event trigger in the event state object as well as
|
|
||||||
* string representation of the subclasses.
|
|
||||||
*
|
|
||||||
* @return string representation of the event trigger
|
|
||||||
*/
|
|
||||||
protected String getNameString()
|
|
||||||
{
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
result.append('[');
|
|
||||||
result.append(_objectName);
|
|
||||||
result.append(":");
|
|
||||||
result.append(_attributeName);
|
|
||||||
result.append("]");
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean getSaveAll()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected TYPE getValue(CompositeData compValue, String fieldName)
|
|
||||||
{
|
|
||||||
int pos = fieldName.indexOf('.');
|
|
||||||
if (pos < 0)
|
|
||||||
return (TYPE)compValue.get(fieldName);
|
|
||||||
else
|
|
||||||
return getValue((CompositeData)compValue.get(fieldName.substring(0, pos)),
|
|
||||||
fieldName.substring(pos+1));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.triggers;
|
|
||||||
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EqualToAttrEventTrigger
|
|
||||||
* <p>
|
|
||||||
* Event trigger that polls a value of an MXBean attribute and
|
|
||||||
* checks if it is equal to specified value.
|
|
||||||
* @param <TYPE> the event trigger type
|
|
||||||
*/
|
|
||||||
public class EqualToAttrEventTrigger<TYPE extends Comparable<TYPE>> extends AttrEventTrigger<TYPE>
|
|
||||||
{
|
|
||||||
protected final TYPE _value;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct event trigger and specify the MXBean attribute
|
|
||||||
* that will be polled by this event trigger as well as the
|
|
||||||
* target value of the attribute.
|
|
||||||
*
|
|
||||||
* @param objectName object name of an MBean to be polled
|
|
||||||
* @param attributeName name of an MBean attribute to be polled
|
|
||||||
* @param value target value of the attribute
|
|
||||||
*
|
|
||||||
* @throws MalformedObjectNameException if unable to find object due to name issue
|
|
||||||
* @throws IllegalArgumentException on invalid parameters
|
|
||||||
*/
|
|
||||||
public EqualToAttrEventTrigger(String objectName, String attributeName, TYPE value)
|
|
||||||
throws MalformedObjectNameException, IllegalArgumentException
|
|
||||||
{
|
|
||||||
super(objectName,attributeName);
|
|
||||||
|
|
||||||
if (value == null)
|
|
||||||
throw new IllegalArgumentException("Value cannot be null");
|
|
||||||
|
|
||||||
_value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Compare the value of the MXBean attribute being polling
|
|
||||||
* to check if it is equal to the specified value.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean match(Comparable<TYPE> value)
|
|
||||||
{
|
|
||||||
return (value.compareTo(_value) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Returns the string representation of this event trigger
|
|
||||||
* in the format "name=value".
|
|
||||||
*
|
|
||||||
* @return string representation of the event trigger
|
|
||||||
*
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
result.append(getNameString());
|
|
||||||
result.append("==");
|
|
||||||
result.append(_value);
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.triggers;
|
|
||||||
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GreaterThanAttrEventTrigger
|
|
||||||
* <p>
|
|
||||||
* Event trigger that polls a value of an MXBean attribute and
|
|
||||||
* checks if it is greater than specified min value.
|
|
||||||
* @param <TYPE> event trigger type
|
|
||||||
*/
|
|
||||||
public class GreaterThanAttrEventTrigger<TYPE extends Comparable<TYPE>> extends AttrEventTrigger<TYPE>
|
|
||||||
{
|
|
||||||
protected final TYPE _min;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct event trigger and specify the MXBean attribute
|
|
||||||
* that will be polled by this event trigger as well as min
|
|
||||||
* value of the attribute.
|
|
||||||
*
|
|
||||||
* @param objectName object name of an MBean to be polled
|
|
||||||
* @param attributeName name of an MBean attribute to be polled
|
|
||||||
* @param min minimum value of the attribute
|
|
||||||
*
|
|
||||||
* @throws MalformedObjectNameException on bad object name
|
|
||||||
* @throws IllegalArgumentException on bad parameters
|
|
||||||
*/
|
|
||||||
public GreaterThanAttrEventTrigger(String objectName, String attributeName, TYPE min)
|
|
||||||
throws MalformedObjectNameException, IllegalArgumentException
|
|
||||||
{
|
|
||||||
super(objectName,attributeName);
|
|
||||||
|
|
||||||
if (min == null)
|
|
||||||
throw new IllegalArgumentException("Value cannot be null");
|
|
||||||
|
|
||||||
_min = min;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Compare the value of the MXBean attribute being polling
|
|
||||||
* to check if it is greater than the min value.
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean match(Comparable<TYPE> value)
|
|
||||||
{
|
|
||||||
return (value.compareTo(_min) > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Returns the string representation of this event trigger
|
|
||||||
* in the format "min<name".
|
|
||||||
*
|
|
||||||
* @return string representation of the event trigger
|
|
||||||
*
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
result.append(_min);
|
|
||||||
result.append("<");
|
|
||||||
result.append(getNameString());
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.triggers;
|
|
||||||
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GreaterThanOrEqualToAttrEventTrigger
|
|
||||||
* <p>
|
|
||||||
* Event trigger that polls a value of an MXBean attribute and
|
|
||||||
* checks if it is greater than or equal to specified min value.
|
|
||||||
* @param <TYPE> event trigger type
|
|
||||||
*/
|
|
||||||
public class GreaterThanOrEqualToAttrEventTrigger<TYPE extends Comparable<TYPE>> extends AttrEventTrigger<TYPE>
|
|
||||||
{
|
|
||||||
protected final TYPE _min;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct event trigger and specify the MXBean attribute
|
|
||||||
* that will be polled by this event trigger as well as min
|
|
||||||
* value of the attribute.
|
|
||||||
*
|
|
||||||
* @param objectName object name of an MBean to be polled
|
|
||||||
* @param attributeName name of an MBean attribute to be polled
|
|
||||||
* @param min minimum value of the attribute
|
|
||||||
*
|
|
||||||
* @throws MalformedObjectNameException on bad object name
|
|
||||||
* @throws IllegalArgumentException on bad parameters
|
|
||||||
*/
|
|
||||||
public GreaterThanOrEqualToAttrEventTrigger(String objectName, String attributeName, TYPE min)
|
|
||||||
throws MalformedObjectNameException, IllegalArgumentException
|
|
||||||
{
|
|
||||||
super(objectName,attributeName);
|
|
||||||
|
|
||||||
if (min == null)
|
|
||||||
throw new IllegalArgumentException("Value cannot be null");
|
|
||||||
|
|
||||||
_min = min;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Compare the value of the MXBean attribute being polling
|
|
||||||
* to check if it is greater than or equal to the min value.
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean match(Comparable<TYPE> value)
|
|
||||||
{
|
|
||||||
return (value.compareTo(_min) >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Returns the string representation of this event trigger
|
|
||||||
* in the format "min<=name".
|
|
||||||
*
|
|
||||||
* @return string representation of the event trigger
|
|
||||||
*
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
result.append(_min);
|
|
||||||
result.append("<=");
|
|
||||||
result.append(getNameString());
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.triggers;
|
|
||||||
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LessThanAttrEventTrigger
|
|
||||||
* <p>
|
|
||||||
* Event trigger that polls a value of an MXBean attribute and
|
|
||||||
* checks if it is greater than specified max value.
|
|
||||||
* @param <TYPE> event trigger type
|
|
||||||
*/
|
|
||||||
public class LessThanAttrEventTrigger<TYPE extends Comparable<TYPE>> extends AttrEventTrigger<TYPE>
|
|
||||||
{
|
|
||||||
protected final TYPE _max;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct event trigger and specify the MXBean attribute
|
|
||||||
* that will be polled by this event trigger as well as max
|
|
||||||
* value of the attribute.
|
|
||||||
*
|
|
||||||
* @param objectName object name of an MBean to be polled
|
|
||||||
* @param attributeName name of an MBean attribute to be polled
|
|
||||||
* @param max maximum value of the attribute
|
|
||||||
*
|
|
||||||
* @throws MalformedObjectNameException on bad object name
|
|
||||||
* @throws IllegalArgumentException on bad parameters
|
|
||||||
*/
|
|
||||||
public LessThanAttrEventTrigger(String objectName, String attributeName, TYPE max)
|
|
||||||
throws MalformedObjectNameException, IllegalArgumentException
|
|
||||||
{
|
|
||||||
super(objectName,attributeName);
|
|
||||||
|
|
||||||
if (max == null)
|
|
||||||
throw new IllegalArgumentException("Value cannot be null");
|
|
||||||
|
|
||||||
_max = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Compare the value of the MXBean attribute being polling
|
|
||||||
* to check if it is less than the min value.
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean match(Comparable<TYPE> value)
|
|
||||||
{
|
|
||||||
return (value.compareTo(_max) < 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Returns the string representation of this event trigger
|
|
||||||
* in the format "name<max".
|
|
||||||
*
|
|
||||||
* @return string representation of the event trigger
|
|
||||||
*
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
result.append(getNameString());
|
|
||||||
result.append("<");
|
|
||||||
result.append(_max);
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.triggers;
|
|
||||||
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LessThanOrEqualToAttrEventTrigger
|
|
||||||
* <p>
|
|
||||||
* Event trigger that polls a value of an MXBean attribute and
|
|
||||||
* checks if it is less than or equal to specified max value.
|
|
||||||
* @param <TYPE> event trigger type
|
|
||||||
*/
|
|
||||||
public class LessThanOrEqualToAttrEventTrigger<TYPE extends Comparable<TYPE>> extends AttrEventTrigger<TYPE>
|
|
||||||
{
|
|
||||||
protected final TYPE _max;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct event trigger and specify the MXBean attribute
|
|
||||||
* that will be polled by this event trigger as well as max
|
|
||||||
* value of the attribute.
|
|
||||||
*
|
|
||||||
* @param objectName object name of an MBean to be polled
|
|
||||||
* @param attributeName name of an MBean attribute to be polled
|
|
||||||
* @param max maximum value of the attribute
|
|
||||||
*
|
|
||||||
* @throws MalformedObjectNameException on bad object name
|
|
||||||
* @throws IllegalArgumentException on bad parameters
|
|
||||||
*/
|
|
||||||
public LessThanOrEqualToAttrEventTrigger(String objectName, String attributeName, TYPE max)
|
|
||||||
throws MalformedObjectNameException, IllegalArgumentException
|
|
||||||
{
|
|
||||||
super(objectName,attributeName);
|
|
||||||
|
|
||||||
if (max == null)
|
|
||||||
throw new IllegalArgumentException("Value cannot be null");
|
|
||||||
|
|
||||||
_max = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Compare the value of the MXBean attribute being polling
|
|
||||||
* to check if it is less than or equal to the max value.
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean match(Comparable<TYPE> value)
|
|
||||||
{
|
|
||||||
return (value.compareTo(_max) <= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Returns the string representation of this event trigger
|
|
||||||
* in the format "name<=max".
|
|
||||||
*
|
|
||||||
* @return string representation of the event trigger
|
|
||||||
*
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
result.append(getNameString());
|
|
||||||
result.append("<=");
|
|
||||||
result.append(_max);
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,138 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.triggers;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventState;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventTrigger;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* AndEventTrigger
|
|
||||||
*
|
|
||||||
* EventTrigger aggregation using logical OR operation
|
|
||||||
* that executes matching of the aggregated event triggers
|
|
||||||
* in left to right order
|
|
||||||
*/
|
|
||||||
public class OrEventTrigger
|
|
||||||
extends EventTrigger
|
|
||||||
{
|
|
||||||
private final List<EventTrigger> _triggers;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct an event trigger and associate the list
|
|
||||||
* of event triggers to be aggregated by this trigger
|
|
||||||
*
|
|
||||||
* @param triggers list of event triggers to add
|
|
||||||
*/
|
|
||||||
public OrEventTrigger(List<EventTrigger> triggers)
|
|
||||||
{
|
|
||||||
_triggers = triggers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct an event trigger and associate the array
|
|
||||||
* of event triggers to be aggregated by this trigger
|
|
||||||
*
|
|
||||||
* @param triggers array of event triggers to add
|
|
||||||
*/
|
|
||||||
public OrEventTrigger(EventTrigger... triggers)
|
|
||||||
{
|
|
||||||
_triggers = Arrays.asList(triggers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Verify if the event trigger conditions are in the
|
|
||||||
* appropriate state for an event to be triggered.
|
|
||||||
* This event trigger will match if any of aggregated
|
|
||||||
* event triggers would return a match.
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.jmx.EventTrigger#match(long)
|
|
||||||
*/
|
|
||||||
public boolean match(long timestamp)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
for(EventTrigger trigger : _triggers)
|
|
||||||
{
|
|
||||||
if (trigger.match(timestamp))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Retrieve the event state associated with specified invocation
|
|
||||||
* of the event trigger match method. This event trigger retrieves
|
|
||||||
* the combined event state of all aggregated event triggers.
|
|
||||||
*
|
|
||||||
* @param timestamp time stamp associated with invocation
|
|
||||||
* @return event state or null if not found
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.jmx.EventTrigger#getState(long)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public EventState getState(long timestamp)
|
|
||||||
{
|
|
||||||
EventState state = new EventState();
|
|
||||||
|
|
||||||
for (EventTrigger trigger : _triggers)
|
|
||||||
{
|
|
||||||
EventState subState = trigger.getState(timestamp);
|
|
||||||
if (subState!=null)
|
|
||||||
{
|
|
||||||
state.addAll(subState.values());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Returns the string representation of this event trigger
|
|
||||||
* in the format "OR(triger1,trigger2,...)".
|
|
||||||
*
|
|
||||||
* @return string representation of the event trigger
|
|
||||||
*
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
int cnt = 0;
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
result.append("OR(");
|
|
||||||
for (EventTrigger trigger : _triggers)
|
|
||||||
{
|
|
||||||
result.append(cnt++ > 0 ? "," : "");
|
|
||||||
result.append(trigger);
|
|
||||||
}
|
|
||||||
result.append(')');
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,99 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.triggers;
|
|
||||||
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RangeAttrEventTrigger
|
|
||||||
* <p>
|
|
||||||
* Event trigger that polls a value of an MXBean attribute and
|
|
||||||
* checks if it is in a range from specified min value to
|
|
||||||
* specified max value.
|
|
||||||
* @param <TYPE> event trigger type
|
|
||||||
*/
|
|
||||||
public class RangeAttrEventTrigger<TYPE extends Comparable<TYPE>> extends AttrEventTrigger<TYPE>
|
|
||||||
{
|
|
||||||
protected final TYPE _min;
|
|
||||||
protected final TYPE _max;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct event trigger and specify the MXBean attribute
|
|
||||||
* that will be polled by this event trigger as well as min
|
|
||||||
* and max value of the attribute.
|
|
||||||
*
|
|
||||||
* @param objectName object name of an MBean to be polled
|
|
||||||
* @param attributeName name of an MBean attribute to be polled
|
|
||||||
* @param min minimum value of the attribute
|
|
||||||
* @param max maximum value of the attribute
|
|
||||||
*
|
|
||||||
* @throws MalformedObjectNameException on bad object name
|
|
||||||
* @throws IllegalArgumentException on bad parameters
|
|
||||||
*/
|
|
||||||
public RangeAttrEventTrigger(String objectName, String attributeName,TYPE min, TYPE max)
|
|
||||||
throws MalformedObjectNameException, IllegalArgumentException
|
|
||||||
{
|
|
||||||
super(objectName,attributeName);
|
|
||||||
|
|
||||||
if (min == null)
|
|
||||||
throw new IllegalArgumentException("Value cannot be null");
|
|
||||||
if (max == null)
|
|
||||||
throw new IllegalArgumentException("Value cannot be null");
|
|
||||||
|
|
||||||
_min = min;
|
|
||||||
_max = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Compare the value of the MXBean attribute being polling
|
|
||||||
* to check if it is in a range from specified min value to
|
|
||||||
* specified max value.
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean match(Comparable<TYPE> value)
|
|
||||||
{
|
|
||||||
return (value.compareTo(_min) > 0) &&(value.compareTo(_max) < 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Returns the string representation of this event trigger
|
|
||||||
* in the format "min<name<max".
|
|
||||||
*
|
|
||||||
* @return string representation of the event trigger
|
|
||||||
*
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
result.append(_min);
|
|
||||||
result.append("<");
|
|
||||||
result.append(getNameString());
|
|
||||||
result.append("<");
|
|
||||||
result.append(_max);
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,99 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor.triggers;
|
|
||||||
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RangeInclAttrEventTrigger
|
|
||||||
* <p>
|
|
||||||
* Event trigger that polls a value of an MXBean attribute and
|
|
||||||
* checks if it is in a range from specified min value to
|
|
||||||
* specified max value including the range bounds.
|
|
||||||
* @param <TYPE> event trigger type
|
|
||||||
*/
|
|
||||||
public class RangeInclAttrEventTrigger<TYPE extends Comparable<TYPE>> extends AttrEventTrigger<TYPE>
|
|
||||||
{
|
|
||||||
protected final TYPE _min;
|
|
||||||
protected final TYPE _max;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Construct event trigger and specify the MXBean attribute
|
|
||||||
* that will be polled by this event trigger as well as min
|
|
||||||
* and max value of the attribute.
|
|
||||||
*
|
|
||||||
* @param objectName object name of an MBean to be polled
|
|
||||||
* @param attributeName name of an MBean attribute to be polled
|
|
||||||
* @param min minimum value of the attribute
|
|
||||||
* @param max maximum value of the attribute
|
|
||||||
*
|
|
||||||
* @throws MalformedObjectNameException on bad object name
|
|
||||||
* @throws IllegalArgumentException on bad parameters
|
|
||||||
*/
|
|
||||||
public RangeInclAttrEventTrigger(String objectName, String attributeName,TYPE min, TYPE max)
|
|
||||||
throws MalformedObjectNameException, IllegalArgumentException
|
|
||||||
{
|
|
||||||
super(objectName,attributeName);
|
|
||||||
|
|
||||||
if (min == null)
|
|
||||||
throw new IllegalArgumentException("Value cannot be null");
|
|
||||||
if (max == null)
|
|
||||||
throw new IllegalArgumentException("Value cannot be null");
|
|
||||||
|
|
||||||
_min = min;
|
|
||||||
_max = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Compare the value of the MXBean attribute being polling
|
|
||||||
* to check if it is in a range from specified min value to
|
|
||||||
* specified max value including the range bounds.
|
|
||||||
*
|
|
||||||
* @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean match(Comparable<TYPE> value)
|
|
||||||
{
|
|
||||||
return (value.compareTo(_min) >= 0) &&(value.compareTo(_max) <= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Returns the string representation of this event trigger
|
|
||||||
* in the format "min<=name<=max".
|
|
||||||
*
|
|
||||||
* @return string representation of the event trigger
|
|
||||||
*
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
result.append(_min);
|
|
||||||
result.append("<=");
|
|
||||||
result.append(getNameString());
|
|
||||||
result.append("<=");
|
|
||||||
result.append(_max);
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Jetty Monitor : Triggers for Monitor Events
|
|
||||||
*/
|
|
||||||
package org.eclipse.jetty.monitor.triggers;
|
|
||||||
|
|
|
@ -1,526 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
|
|
||||||
import javax.management.MBeanServer;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.client.HttpClient;
|
|
||||||
import org.eclipse.jetty.client.api.ContentResponse;
|
|
||||||
import org.eclipse.jetty.http.HttpStatus;
|
|
||||||
import org.eclipse.jetty.jmx.MBeanContainer;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.ConsoleNotifier;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventNotifier;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventState;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventState.TriggerState;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.EventTrigger;
|
|
||||||
import org.eclipse.jetty.monitor.jmx.MonitorAction;
|
|
||||||
import org.eclipse.jetty.monitor.triggers.AndEventTrigger;
|
|
||||||
import org.eclipse.jetty.monitor.triggers.AttrEventTrigger;
|
|
||||||
import org.eclipse.jetty.monitor.triggers.EqualToAttrEventTrigger;
|
|
||||||
import org.eclipse.jetty.monitor.triggers.GreaterThanAttrEventTrigger;
|
|
||||||
import org.eclipse.jetty.monitor.triggers.GreaterThanOrEqualToAttrEventTrigger;
|
|
||||||
import org.eclipse.jetty.monitor.triggers.LessThanAttrEventTrigger;
|
|
||||||
import org.eclipse.jetty.monitor.triggers.LessThanOrEqualToAttrEventTrigger;
|
|
||||||
import org.eclipse.jetty.monitor.triggers.OrEventTrigger;
|
|
||||||
import org.eclipse.jetty.monitor.triggers.RangeAttrEventTrigger;
|
|
||||||
import org.eclipse.jetty.monitor.triggers.RangeInclAttrEventTrigger;
|
|
||||||
import org.eclipse.jetty.server.Connector;
|
|
||||||
import org.eclipse.jetty.server.Request;
|
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.server.ServerConnector;
|
|
||||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
public class AttrEventTriggerTest
|
|
||||||
{
|
|
||||||
private static final Logger LOG = Log.getLogger(AttrEventTriggerTest.class);
|
|
||||||
|
|
||||||
private Server _server;
|
|
||||||
private TestHandler _handler;
|
|
||||||
private RequestCounter _counter;
|
|
||||||
private JMXMonitor _monitor;
|
|
||||||
private HttpClient _client;
|
|
||||||
private String _requestUrl;
|
|
||||||
private MBeanContainer _mBeanContainer;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
File docRoot = new File("target/test-output/docroot/");
|
|
||||||
docRoot.mkdirs();
|
|
||||||
docRoot.deleteOnExit();
|
|
||||||
|
|
||||||
System.setProperty("org.eclipse.jetty.util.log.DEBUG","");
|
|
||||||
_server = new Server();
|
|
||||||
|
|
||||||
ServerConnector connector = new ServerConnector(_server);
|
|
||||||
connector.setPort(0);
|
|
||||||
_server.setConnectors(new Connector[] {connector});
|
|
||||||
|
|
||||||
_handler = new TestHandler();
|
|
||||||
_server.setHandler(_handler);
|
|
||||||
|
|
||||||
MBeanContainer.resetUnique();
|
|
||||||
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
|
|
||||||
_mBeanContainer = new MBeanContainer(mBeanServer);
|
|
||||||
_server.addBean(_mBeanContainer,true);
|
|
||||||
_server.addBean(Log.getLog());
|
|
||||||
|
|
||||||
_counter = _handler.getRequestCounter();
|
|
||||||
_server.addBean(_counter);
|
|
||||||
|
|
||||||
_server.start();
|
|
||||||
|
|
||||||
startClient();
|
|
||||||
|
|
||||||
_monitor = new JMXMonitor();
|
|
||||||
|
|
||||||
int port = connector.getLocalPort();
|
|
||||||
_requestUrl = "http://localhost:"+port+ "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
stopClient();
|
|
||||||
|
|
||||||
_mBeanContainer.destroy();
|
|
||||||
|
|
||||||
if (_server != null)
|
|
||||||
{
|
|
||||||
_server.stop();
|
|
||||||
_server = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNoCondition()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
long requestCount = 10;
|
|
||||||
|
|
||||||
AttrEventTrigger<Long> trigger =
|
|
||||||
new AttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter");
|
|
||||||
|
|
||||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
|
||||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
|
||||||
|
|
||||||
performTest(action, requestCount, 1000);
|
|
||||||
|
|
||||||
ResultSet result = new ResultSet(1,requestCount);
|
|
||||||
assertEquals(result, action.getHits());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testEqual_TRUE()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
long requestCount = 10;
|
|
||||||
long testValue = 5;
|
|
||||||
|
|
||||||
EqualToAttrEventTrigger<Long> trigger =
|
|
||||||
new EqualToAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",testValue);
|
|
||||||
|
|
||||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
|
||||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
|
||||||
|
|
||||||
performTest(action, requestCount, 1000);
|
|
||||||
|
|
||||||
ResultSet result = new ResultSet(testValue);
|
|
||||||
assertEquals(result, action.getHits());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testEqual_FALSE()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
long requestCount = 10;
|
|
||||||
long testValue = 11;
|
|
||||||
|
|
||||||
EqualToAttrEventTrigger<Long> trigger =
|
|
||||||
new EqualToAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
|
||||||
testValue);
|
|
||||||
|
|
||||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
|
||||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
|
||||||
|
|
||||||
performTest(action, requestCount, 1000);
|
|
||||||
|
|
||||||
ResultSet result = new ResultSet();
|
|
||||||
assertEquals(result, action.getHits());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLowerLimit()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
long requestCount = 10;
|
|
||||||
long testRangeLow = 5;
|
|
||||||
|
|
||||||
GreaterThanAttrEventTrigger<Long> trigger =
|
|
||||||
new GreaterThanAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
|
||||||
testRangeLow);
|
|
||||||
|
|
||||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
|
||||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
|
||||||
|
|
||||||
performTest(action, requestCount, 1000);
|
|
||||||
|
|
||||||
ResultSet result = new ResultSet(6,10);
|
|
||||||
assertEquals(result, action.getHits());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLowerLimitIncl()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
long requestCount = 10;
|
|
||||||
long testRangeLow = 5;
|
|
||||||
|
|
||||||
GreaterThanOrEqualToAttrEventTrigger<Long> trigger =
|
|
||||||
new GreaterThanOrEqualToAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
|
||||||
testRangeLow);
|
|
||||||
|
|
||||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
|
||||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
|
||||||
|
|
||||||
performTest(action, requestCount, 1000);
|
|
||||||
|
|
||||||
ResultSet result = new ResultSet(5,10);
|
|
||||||
assertEquals(result, action.getHits());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpperLimit()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
long requestCount = 10;
|
|
||||||
long testRangeHigh = 5;
|
|
||||||
|
|
||||||
LessThanAttrEventTrigger<Long> trigger =
|
|
||||||
new LessThanAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
|
||||||
testRangeHigh);
|
|
||||||
|
|
||||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
|
||||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
|
||||||
|
|
||||||
performTest(action, requestCount, 1000);
|
|
||||||
|
|
||||||
ResultSet result = new ResultSet(1,4);
|
|
||||||
assertEquals(result, action.getHits());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpperLimitIncl()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
long requestCount = 10;
|
|
||||||
long testRangeHigh = 5;
|
|
||||||
|
|
||||||
LessThanOrEqualToAttrEventTrigger<Long> trigger =
|
|
||||||
new LessThanOrEqualToAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
|
||||||
testRangeHigh);
|
|
||||||
|
|
||||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
|
||||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
|
||||||
|
|
||||||
performTest(action, requestCount, 1000);
|
|
||||||
|
|
||||||
ResultSet result = new ResultSet(1,5);
|
|
||||||
assertEquals(result, action.getHits());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRangeInclusive()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
long requestCount = 10;
|
|
||||||
long testRangeLow = 3;
|
|
||||||
long testRangeHigh = 8;
|
|
||||||
|
|
||||||
RangeInclAttrEventTrigger<Long> trigger =
|
|
||||||
new RangeInclAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
|
||||||
testRangeLow, testRangeHigh);
|
|
||||||
|
|
||||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
|
||||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
|
||||||
|
|
||||||
performTest(action, requestCount, 1000);
|
|
||||||
|
|
||||||
ResultSet result = new ResultSet(testRangeLow,testRangeHigh);
|
|
||||||
assertEquals(result, action.getHits());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInsideRangeExclusive()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
long requestCount = 10;
|
|
||||||
long testRangeLow = 3;
|
|
||||||
long testRangeHigh = 8;
|
|
||||||
|
|
||||||
RangeAttrEventTrigger<Long> trigger =
|
|
||||||
new RangeAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
|
||||||
testRangeLow, testRangeHigh);
|
|
||||||
|
|
||||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
|
||||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
|
||||||
|
|
||||||
performTest(action, requestCount, 1000);
|
|
||||||
|
|
||||||
ResultSet result = new ResultSet(testRangeLow+1,testRangeHigh-1);
|
|
||||||
assertEquals(result, action.getHits());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRangeComposite()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
long requestCount = 10;
|
|
||||||
long testRangeLow = 4;
|
|
||||||
long testRangeHigh = 7;
|
|
||||||
|
|
||||||
GreaterThanAttrEventTrigger<Long> trigger1 =
|
|
||||||
new GreaterThanAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
|
||||||
testRangeLow);
|
|
||||||
LessThanOrEqualToAttrEventTrigger<Long> trigger2 =
|
|
||||||
new LessThanOrEqualToAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
|
||||||
testRangeHigh);
|
|
||||||
AndEventTrigger trigger = new AndEventTrigger(trigger1, trigger2);
|
|
||||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
|
||||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
|
||||||
|
|
||||||
performTest(action, requestCount, 1000);
|
|
||||||
|
|
||||||
ResultSet result = new ResultSet(testRangeLow+1,testRangeHigh);
|
|
||||||
assertEquals(result, action.getHits());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRangeOuter()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
long requestCount = 10;
|
|
||||||
long testRangeLow = 4;
|
|
||||||
long testRangeHigh = 7;
|
|
||||||
|
|
||||||
LessThanOrEqualToAttrEventTrigger<Long> trigger1 =
|
|
||||||
new LessThanOrEqualToAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
|
||||||
testRangeLow);
|
|
||||||
GreaterThanAttrEventTrigger<Long> trigger2 =
|
|
||||||
new GreaterThanAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
|
||||||
testRangeHigh);
|
|
||||||
OrEventTrigger trigger = new OrEventTrigger(trigger1, trigger2);
|
|
||||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
|
||||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
|
||||||
|
|
||||||
performTest(action, requestCount, 1000);
|
|
||||||
|
|
||||||
ResultSet result = new ResultSet(1,testRangeLow,testRangeHigh+1, requestCount);
|
|
||||||
assertEquals(result, action.getHits());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void performTest(MonitorAction action, long count, long interval)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
_monitor.addActions(action);
|
|
||||||
|
|
||||||
for (long cnt=0; cnt < count; cnt++)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//LOG.debug("Request: %s", _requestUrl);
|
|
||||||
ContentResponse r3sponse = _client.GET(_requestUrl);
|
|
||||||
|
|
||||||
//ContentExchange getExchange = new ContentExchange();
|
|
||||||
//getExchange.setURL(_requestUrl);
|
|
||||||
//getExchange.setMethod(HttpMethods.GET);
|
|
||||||
|
|
||||||
//_client.send(getExchange);
|
|
||||||
//int state = getExchange.waitForDone();
|
|
||||||
|
|
||||||
String content = "";
|
|
||||||
//int responseStatus = getExchange.getResponseStatus();
|
|
||||||
if (r3sponse.getStatus() == HttpStatus.OK_200)
|
|
||||||
{
|
|
||||||
content = r3sponse.getContentAsString();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG.info("response status", r3sponse.getStatus());
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(HttpStatus.OK_200,r3sponse.getStatus());
|
|
||||||
Thread.sleep(interval);
|
|
||||||
}
|
|
||||||
catch (InterruptedException ex)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread.sleep(interval);
|
|
||||||
|
|
||||||
_monitor.removeActions(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void startClient()//Realm realm)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
_client = new HttpClient();
|
|
||||||
//_client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
|
|
||||||
//if (realm != null){
|
|
||||||
// _client.setRealmResolver(new SimpleRealmResolver(realm));
|
|
||||||
//}
|
|
||||||
_client.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void stopClient()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
if (_client != null)
|
|
||||||
{
|
|
||||||
_client.stop();
|
|
||||||
_client = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class TestHandler
|
|
||||||
extends AbstractHandler
|
|
||||||
{
|
|
||||||
private RequestCounter _counter = new RequestCounter();
|
|
||||||
|
|
||||||
public void handle(String target, Request baseRequest,
|
|
||||||
HttpServletRequest request, HttpServletResponse response)
|
|
||||||
throws IOException, ServletException
|
|
||||||
{
|
|
||||||
if (baseRequest.isHandled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_counter.increment();
|
|
||||||
|
|
||||||
response.setContentType("text/plain");
|
|
||||||
response.setStatus(HttpServletResponse.SC_OK);
|
|
||||||
PrintWriter writer = response.getWriter();
|
|
||||||
writer.println("===TEST RESPONSE===");
|
|
||||||
baseRequest.setHandled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestCounter getRequestCounter()
|
|
||||||
{
|
|
||||||
return _counter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class ResultSet extends TreeSet<Long>
|
|
||||||
{
|
|
||||||
public ResultSet() {}
|
|
||||||
|
|
||||||
public ResultSet(long value)
|
|
||||||
{
|
|
||||||
add(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResultSet(long start, long end)
|
|
||||||
{
|
|
||||||
addEntries(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResultSet(long start, long pause, long resume, long end)
|
|
||||||
{
|
|
||||||
addEntries(start, pause);
|
|
||||||
addEntries(resume, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addEntries(long start, long stop)
|
|
||||||
{
|
|
||||||
if (start > 0 && stop > 0)
|
|
||||||
{
|
|
||||||
for(long idx=start; idx <= stop; idx++)
|
|
||||||
{
|
|
||||||
add(idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(ResultSet set)
|
|
||||||
{
|
|
||||||
return (this.size() == set.size()) && containsAll(set);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class CounterAction
|
|
||||||
extends MonitorAction
|
|
||||||
{
|
|
||||||
private ResultSet _hits = new ResultSet();
|
|
||||||
|
|
||||||
public CounterAction(EventTrigger trigger, EventNotifier notifier, long interval, long delay)
|
|
||||||
{
|
|
||||||
super(trigger, notifier, interval, delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void execute(EventTrigger trigger, EventState<?> state, long timestamp)
|
|
||||||
{
|
|
||||||
if (trigger != null && state != null)
|
|
||||||
{
|
|
||||||
Collection<?> values = state.values();
|
|
||||||
|
|
||||||
Iterator<?> it = values.iterator();
|
|
||||||
while(it.hasNext())
|
|
||||||
{
|
|
||||||
TriggerState<?> entry = (TriggerState<?>)it.next();
|
|
||||||
Object value = entry.getValue();
|
|
||||||
if (value != null)
|
|
||||||
{
|
|
||||||
_hits.add((Long)value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResultSet getHits()
|
|
||||||
{
|
|
||||||
return _hits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
|
||||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
|
||||||
import org.eclipse.jetty.util.annotation.ManagedOperation;
|
|
||||||
|
|
||||||
|
|
||||||
@ManagedObject("TEST: Request Counter")
|
|
||||||
public class RequestCounter
|
|
||||||
{
|
|
||||||
public long _counter;
|
|
||||||
|
|
||||||
@ManagedAttribute("Get the value of the counter")
|
|
||||||
public synchronized long getCounter()
|
|
||||||
{
|
|
||||||
return _counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ManagedOperation("Increment the value of the counter")
|
|
||||||
public synchronized void increment()
|
|
||||||
{
|
|
||||||
_counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ManagedOperation("Reset the counter")
|
|
||||||
public synchronized void reset()
|
|
||||||
{
|
|
||||||
_counter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,165 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2018 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.monitor;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.util.component.Dumpable;
|
|
||||||
import org.eclipse.jetty.util.log.StacklessLogging;
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
public class ThreadMonitorTest
|
|
||||||
{
|
|
||||||
public final static int DURATION=4000;
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
public void monitorTest() throws Exception
|
|
||||||
{
|
|
||||||
try(StacklessLogging stackless=new StacklessLogging(ThreadMonitor.class))
|
|
||||||
{
|
|
||||||
|
|
||||||
final AtomicInteger countLogs=new AtomicInteger(0);
|
|
||||||
final AtomicInteger countSpin=new AtomicInteger(0);
|
|
||||||
|
|
||||||
ThreadMonitor monitor = new ThreadMonitor(1000,50,1,1)
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
protected void logThreadInfo(boolean logAll)
|
|
||||||
{
|
|
||||||
if (logAll)
|
|
||||||
countLogs.incrementAndGet();
|
|
||||||
else
|
|
||||||
countSpin.incrementAndGet();
|
|
||||||
super.logThreadInfo(logAll);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
monitor.setDumpable(new Dumpable()
|
|
||||||
{
|
|
||||||
public void dump(Appendable out, String indent) throws IOException
|
|
||||||
{
|
|
||||||
out.append(dump());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String dump()
|
|
||||||
{
|
|
||||||
return "Dump Spinning";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
monitor.logCpuUsage(2000,0);
|
|
||||||
monitor.start();
|
|
||||||
|
|
||||||
Random rnd = new Random();
|
|
||||||
for (long cnt=0; cnt<100; cnt++)
|
|
||||||
{
|
|
||||||
long value = rnd.nextLong() % 50 + 50;
|
|
||||||
Sleeper sleeper = new Sleeper(value);
|
|
||||||
Thread runner = new Thread(sleeper);
|
|
||||||
runner.setDaemon(true);
|
|
||||||
runner.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
Spinner spinner = new Spinner();
|
|
||||||
Thread runner = new Thread(spinner);
|
|
||||||
runner.start();
|
|
||||||
|
|
||||||
Thread.sleep(DURATION);
|
|
||||||
|
|
||||||
spinner.setDone();
|
|
||||||
monitor.stop();
|
|
||||||
|
|
||||||
assertTrue(countLogs.get() >= 1);
|
|
||||||
assertTrue(countSpin.get() >= 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private class Spinner implements Runnable
|
|
||||||
{
|
|
||||||
private volatile boolean done = false;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void setDone()
|
|
||||||
{
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
spin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void spin()
|
|
||||||
{
|
|
||||||
long result=-1;
|
|
||||||
long end=TimeUnit.NANOSECONDS.toMillis(System.nanoTime())+DURATION+1000;
|
|
||||||
while (!done && TimeUnit.NANOSECONDS.toMillis(System.nanoTime())<end)
|
|
||||||
{
|
|
||||||
for (int i=0;i<1000000000;i++)
|
|
||||||
result^=i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result==42)
|
|
||||||
System.err.println("Bingo!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Sleeper implements Runnable
|
|
||||||
{
|
|
||||||
private long _value;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Sleeper(long value)
|
|
||||||
{
|
|
||||||
_value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
fn(_value);
|
|
||||||
}
|
|
||||||
catch (InterruptedException e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public long fn(long value) throws InterruptedException
|
|
||||||
{
|
|
||||||
long result = value > 1 ? fn(value-1) : 1;
|
|
||||||
|
|
||||||
Thread.sleep(50);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
|
||||||
#org.eclipse.jetty.LEVEL=DEBUG
|
|
||||||
#org.eclipse.jetty.monitor.LEVEL=DEBUG
|
|
|
@ -225,7 +225,7 @@ public class ResourceService
|
||||||
|
|
||||||
String pathInContext=URIUtil.addPaths(servletPath,pathInfo);
|
String pathInContext=URIUtil.addPaths(servletPath,pathInfo);
|
||||||
|
|
||||||
boolean endsWithSlash=(pathInfo==null?request.getServletPath():pathInfo).endsWith(URIUtil.SLASH);
|
boolean endsWithSlash=(pathInfo==null?servletPath:pathInfo).endsWith(URIUtil.SLASH);
|
||||||
boolean checkPrecompressedVariants=_precompressedFormats.length > 0 && !endsWithSlash && !included && reqRanges==null;
|
boolean checkPrecompressedVariants=_precompressedFormats.length > 0 && !endsWithSlash && !included && reqRanges==null;
|
||||||
|
|
||||||
HttpContent content=null;
|
HttpContent content=null;
|
||||||
|
@ -254,7 +254,7 @@ public class ResourceService
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strip slash?
|
// Strip slash?
|
||||||
if (endsWithSlash && pathInContext.length()>1)
|
if (!included && endsWithSlash && pathInContext.length()>1)
|
||||||
{
|
{
|
||||||
String q=request.getQueryString();
|
String q=request.getQueryString();
|
||||||
pathInContext=pathInContext.substring(0,pathInContext.length()-1);
|
pathInContext=pathInContext.substring(0,pathInContext.length()-1);
|
||||||
|
|
|
@ -619,9 +619,9 @@ public class Response implements HttpServletResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_mimeType=null;
|
|
||||||
_characterEncoding=null;
|
|
||||||
_outputType = OutputType.NONE;
|
_outputType = OutputType.NONE;
|
||||||
|
setContentType(null);
|
||||||
|
setCharacterEncoding(null);
|
||||||
setHeader(HttpHeader.EXPIRES,null);
|
setHeader(HttpHeader.EXPIRES,null);
|
||||||
setHeader(HttpHeader.LAST_MODIFIED,null);
|
setHeader(HttpHeader.LAST_MODIFIED,null);
|
||||||
setHeader(HttpHeader.CACHE_CONTROL,null);
|
setHeader(HttpHeader.CACHE_CONTROL,null);
|
||||||
|
|
|
@ -19,30 +19,34 @@
|
||||||
package org.eclipse.jetty.server;
|
package org.eclipse.jetty.server;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
import static org.hamcrest.Matchers.startsWith;
|
import static org.hamcrest.Matchers.startsWith;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.HttpField;
|
||||||
|
import org.eclipse.jetty.http.HttpHeader;
|
||||||
|
import org.eclipse.jetty.http.HttpTester;
|
||||||
|
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||||
import org.eclipse.jetty.server.handler.ErrorHandler;
|
import org.eclipse.jetty.server.handler.ErrorHandler;
|
||||||
import org.eclipse.jetty.toolchain.test.AdvancedRunner;
|
import org.junit.AfterClass;
|
||||||
import org.junit.After;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
@RunWith(AdvancedRunner.class)
|
|
||||||
public class ErrorHandlerTest
|
public class ErrorHandlerTest
|
||||||
{
|
{
|
||||||
Server server;
|
static Server server;
|
||||||
LocalConnector connector;
|
static LocalConnector connector;
|
||||||
|
|
||||||
@Before
|
@BeforeClass
|
||||||
public void before() throws Exception
|
public static void before() throws Exception
|
||||||
{
|
{
|
||||||
server = new Server();
|
server = new Server();
|
||||||
connector = new LocalConnector(server);
|
connector = new LocalConnector(server);
|
||||||
|
@ -72,17 +76,36 @@ public class ErrorHandlerTest
|
||||||
.append("}");
|
.append("}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "text/plain":
|
||||||
|
{
|
||||||
|
baseRequest.setHandled(true);
|
||||||
|
response.setContentType("text/plain");
|
||||||
|
response.getOutputStream().print(response.getContentType());
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
super.generateAcceptableResponse(baseRequest,request,response,code,message,mimeType);
|
super.generateAcceptableResponse(baseRequest,request,response,code,message,mimeType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
server.setHandler(new AbstractHandler()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
if(target.startsWith("/charencoding/"))
|
||||||
|
{
|
||||||
|
response.setCharacterEncoding("utf-8");
|
||||||
|
response.sendError(404);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
server.start();
|
server.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@AfterClass
|
||||||
public void after() throws Exception
|
public static void after() throws Exception
|
||||||
{
|
{
|
||||||
server.stop();
|
server.stop();
|
||||||
}
|
}
|
||||||
|
@ -260,4 +283,19 @@ public class ErrorHandlerTest
|
||||||
assertThat(response,containsString("Content-Type: text/json"));
|
assertThat(response,containsString("Content-Type: text/json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCharEncoding() throws Exception
|
||||||
|
{
|
||||||
|
String rawResponse = connector.getResponse(
|
||||||
|
"GET /charencoding/foo HTTP/1.1\r\n"+
|
||||||
|
"Host: Localhost\r\n"+
|
||||||
|
"Accept: text/plain\r\n"+
|
||||||
|
"\r\n");
|
||||||
|
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
|
||||||
|
|
||||||
|
assertThat("Response status code", response.getStatus(), is(404));
|
||||||
|
HttpField contentType = response.getField(HttpHeader.CONTENT_TYPE);
|
||||||
|
assertThat("Response Content-Type", contentType, is(notNullValue()));
|
||||||
|
assertThat("Response Content-Type value", contentType.getValue(), not(containsString("null")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,28 +218,28 @@ public class LowResourcesMonitorTest
|
||||||
@Test
|
@Test
|
||||||
public void testMaxLowResourceTime() throws Exception
|
public void testMaxLowResourceTime() throws Exception
|
||||||
{
|
{
|
||||||
_lowResourcesMonitor.setMaxLowResourcesTime(2000);
|
_lowResourcesMonitor.setMaxLowResourcesTime(5000);
|
||||||
Assert.assertFalse(_lowResourcesMonitor.isLowOnResources());
|
Assert.assertFalse(_lowResourcesMonitor.isLowOnResources());
|
||||||
|
|
||||||
try(Socket socket0 = new Socket("localhost",_connector.getLocalPort()))
|
try(Socket socket0 = new Socket("localhost",_connector.getLocalPort()))
|
||||||
{
|
{
|
||||||
_lowResourcesMonitor.setMaxMemory(1);
|
_lowResourcesMonitor.setMaxMemory(1);
|
||||||
|
|
||||||
Thread.sleep(1200);
|
Thread.sleep(2400);
|
||||||
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
|
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
|
||||||
|
|
||||||
try(Socket socket1 = new Socket("localhost",_connector.getLocalPort()))
|
try(Socket socket1 = new Socket("localhost",_connector.getLocalPort()))
|
||||||
{
|
{
|
||||||
Thread.sleep(1200);
|
Thread.sleep(2400);
|
||||||
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
|
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
|
||||||
Assert.assertEquals(-1,socket0.getInputStream().read());
|
Assert.assertEquals(-1,socket0.getInputStream().read());
|
||||||
socket1.getOutputStream().write("G".getBytes(StandardCharsets.UTF_8));
|
socket1.getOutputStream().write("G".getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
Thread.sleep(1200);
|
Thread.sleep(2400);
|
||||||
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
|
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
|
||||||
socket1.getOutputStream().write("E".getBytes(StandardCharsets.UTF_8));
|
socket1.getOutputStream().write("E".getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
Thread.sleep(1200);
|
Thread.sleep(2400);
|
||||||
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
|
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
|
||||||
Assert.assertEquals(-1,socket1.getInputStream().read());
|
Assert.assertEquals(-1,socket1.getInputStream().read());
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.component.LifeCycle;
|
import org.eclipse.jetty.util.component.LifeCycle;
|
||||||
|
@ -153,37 +154,53 @@ public class ExecutionStrategyTest
|
||||||
{
|
{
|
||||||
final int TASKS = 3*_threads.getMaxThreads();
|
final int TASKS = 3*_threads.getMaxThreads();
|
||||||
final BlockingQueue<CountDownLatch> q = new ArrayBlockingQueue<>(_threads.getMaxThreads());
|
final BlockingQueue<CountDownLatch> q = new ArrayBlockingQueue<>(_threads.getMaxThreads());
|
||||||
|
final AtomicInteger taken = new AtomicInteger(0);
|
||||||
|
final AtomicInteger run = new AtomicInteger(0);
|
||||||
|
final AtomicBoolean producing = new AtomicBoolean(false);
|
||||||
|
|
||||||
Producer producer = new TestProducer()
|
Producer producer = new TestProducer()
|
||||||
{
|
{
|
||||||
int tasks=TASKS;
|
AtomicInteger tasks = new AtomicInteger(TASKS);
|
||||||
@Override
|
@Override
|
||||||
public Runnable produce()
|
public Runnable produce()
|
||||||
{
|
{
|
||||||
final int id = --tasks;
|
final int id = tasks.decrementAndGet();
|
||||||
if (id>=0)
|
try
|
||||||
{
|
{
|
||||||
while(_threads.isRunning())
|
if (!producing.compareAndSet(false,true))
|
||||||
|
System.err.println("MULTIPLE PRODUCERS "+id);
|
||||||
|
|
||||||
|
if (id>=0)
|
||||||
{
|
{
|
||||||
try
|
while(_threads.isRunning())
|
||||||
{
|
{
|
||||||
final CountDownLatch latch = q.take();
|
try
|
||||||
return new Runnable()
|
|
||||||
{
|
{
|
||||||
@Override
|
final CountDownLatch latch = q.take();
|
||||||
public void run()
|
taken.incrementAndGet();
|
||||||
|
return new Runnable()
|
||||||
{
|
{
|
||||||
// System.err.println("RUN "+id);
|
@Override
|
||||||
latch.countDown();
|
public void run()
|
||||||
}
|
{
|
||||||
};
|
run.incrementAndGet();
|
||||||
}
|
// System.err.println("RUN "+id);
|
||||||
catch(InterruptedException e)
|
latch.countDown();
|
||||||
{
|
}
|
||||||
e.printStackTrace();
|
};
|
||||||
|
}
|
||||||
|
catch(InterruptedException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (!producing.compareAndSet(true,false))
|
||||||
|
System.err.println("Multiple produced "+id);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -218,6 +235,7 @@ public class ExecutionStrategyTest
|
||||||
if (!latch.await(30,TimeUnit.SECONDS))
|
if (!latch.await(30,TimeUnit.SECONDS))
|
||||||
{
|
{
|
||||||
System.err.println(_strategy);
|
System.err.println(_strategy);
|
||||||
|
System.err.printf("tasks=%d latch=%d taken=%d run=%d q=%d%n",TASKS,latch.getCount(),taken.get(),run.get(), q.size());
|
||||||
_threads.dumpStdErr();
|
_threads.dumpStdErr();
|
||||||
Assert.fail();
|
Assert.fail();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue