Merge branch 'jetty-9.4.x' of github.com:eclipse/jetty.project into jetty-9.4.x

This commit is contained in:
Joakim Erdfelt 2018-03-14 10:29:50 -05:00
commit 3ca6f95e0a
53 changed files with 101 additions and 5257 deletions

View File

@ -1,5 +1,5 @@
<?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">
<Ref refid="DeploymentManager">

View File

@ -1,5 +1,5 @@
<?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">
<Ref id="httpConnector">

View File

@ -1,5 +1,5 @@
<?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">
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">

View File

@ -1,5 +1,5 @@
<?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">
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">

View File

@ -1,5 +1,5 @@
<?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">
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">

View File

@ -1,5 +1,5 @@
<?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">
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">

View File

@ -1,5 +1,5 @@
<?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">
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">

View File

@ -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.

View 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>

View File

@ -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>

View File

@ -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

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}
}
});
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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&lt;TYPE&gt;)
* 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));
}
}

View File

@ -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();
}
}

View File

@ -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&lt;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();
}
}

View File

@ -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&lt;=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();
}
}

View File

@ -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&lt;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();
}
}

View File

@ -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&lt;=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();
}
}

View File

@ -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();
}
}

View File

@ -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&lt;name&lt;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();
}
}

View File

@ -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&lt;=name&lt;=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();
}
}

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -225,7 +225,7 @@ public class ResourceService
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;
HttpContent content=null;
@ -254,7 +254,7 @@ public class ResourceService
}
// Strip slash?
if (endsWithSlash && pathInContext.length()>1)
if (!included && endsWithSlash && pathInContext.length()>1)
{
String q=request.getQueryString();
pathInContext=pathInContext.substring(0,pathInContext.length()-1);

View File

@ -619,9 +619,9 @@ public class Response implements HttpServletResponse
}
_mimeType=null;
_characterEncoding=null;
_outputType = OutputType.NONE;
setContentType(null);
setCharacterEncoding(null);
setHeader(HttpHeader.EXPIRES,null);
setHeader(HttpHeader.LAST_MODIFIED,null);
setHeader(HttpHeader.CACHE_CONTROL,null);

View File

@ -19,30 +19,34 @@
package org.eclipse.jetty.server;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.*;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
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.toolchain.test.AdvancedRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AdvancedRunner.class)
public class ErrorHandlerTest
{
Server server;
LocalConnector connector;
static Server server;
static LocalConnector connector;
@Before
public void before() throws Exception
@BeforeClass
public static void before() throws Exception
{
server = new Server();
connector = new LocalConnector(server);
@ -72,17 +76,36 @@ public class ErrorHandlerTest
.append("}");
break;
}
case "text/plain":
{
baseRequest.setHandled(true);
response.setContentType("text/plain");
response.getOutputStream().print(response.getContentType());
break;
}
default:
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();
}
@After
public void after() throws Exception
@AfterClass
public static void after() throws Exception
{
server.stop();
}
@ -260,4 +283,19 @@ public class ErrorHandlerTest
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")));
}
}

View File

@ -218,28 +218,28 @@ public class LowResourcesMonitorTest
@Test
public void testMaxLowResourceTime() throws Exception
{
_lowResourcesMonitor.setMaxLowResourcesTime(2000);
_lowResourcesMonitor.setMaxLowResourcesTime(5000);
Assert.assertFalse(_lowResourcesMonitor.isLowOnResources());
try(Socket socket0 = new Socket("localhost",_connector.getLocalPort()))
{
_lowResourcesMonitor.setMaxMemory(1);
Thread.sleep(1200);
Thread.sleep(2400);
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
try(Socket socket1 = new Socket("localhost",_connector.getLocalPort()))
{
Thread.sleep(1200);
Thread.sleep(2400);
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
Assert.assertEquals(-1,socket0.getInputStream().read());
socket1.getOutputStream().write("G".getBytes(StandardCharsets.UTF_8));
Thread.sleep(1200);
Thread.sleep(2400);
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
socket1.getOutputStream().write("E".getBytes(StandardCharsets.UTF_8));
Thread.sleep(1200);
Thread.sleep(2400);
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
Assert.assertEquals(-1,socket1.getInputStream().read());
}

View File

@ -29,6 +29,7 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jetty.util.component.LifeCycle;
@ -153,37 +154,53 @@ public class ExecutionStrategyTest
{
final int TASKS = 3*_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()
{
int tasks=TASKS;
AtomicInteger tasks = new AtomicInteger(TASKS);
@Override
public Runnable produce()
{
final int id = --tasks;
if (id>=0)
final int id = tasks.decrementAndGet();
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();
return new Runnable()
try
{
@Override
public void run()
final CountDownLatch latch = q.take();
taken.incrementAndGet();
return new Runnable()
{
// System.err.println("RUN "+id);
latch.countDown();
}
};
}
catch(InterruptedException e)
{
e.printStackTrace();
@Override
public void run()
{
run.incrementAndGet();
// System.err.println("RUN "+id);
latch.countDown();
}
};
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
finally
{
if (!producing.compareAndSet(true,false))
System.err.println("Multiple produced "+id);
}
return null;
}
@ -218,6 +235,7 @@ public class ExecutionStrategyTest
if (!latch.await(30,TimeUnit.SECONDS))
{
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();
Assert.fail();
}