Merge branch 'master' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project

This commit is contained in:
Greg Wilkins 2011-08-24 10:29:02 +10:00
commit f81903388e
42 changed files with 4862 additions and 7 deletions

View File

@ -1,3 +1,20 @@
<!--
// ========================================================================
// Copyright (c) Webtide LLC
//
// 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.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
-->
<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>
@ -10,6 +27,9 @@
<description>Performance monitoring artifact for jetty.</description>
<properties>
<bundle-symbolic-name>${project.groupId}.jmx</bundle-symbolic-name>
<test-wars-dir>${project.build.directory}/test-wars</test-wars-dir>
<test-libs-dir>${project.build.directory}/test-libs</test-libs-dir>
<test-dist-dir>${project.build.directory}/test-dist</test-dist-dir>
</properties>
<build>
<plugins>
@ -59,6 +79,41 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>always</forkMode>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-jetty-distro</id>
<phase>process-test-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-distribution</artifactId>
<version>${project.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
</artifactItems>
<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>
<outputDirectory>${test-dist-dir}</outputDirectory>
<overWriteSnapshots>true</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
@ -69,15 +124,52 @@
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<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-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>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,189 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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
*
* 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
*/
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

@ -23,6 +23,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jetty.monitor.thread.ThreadMonitorException;
import org.eclipse.jetty.monitor.thread.ThreadMonitorInfo;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;

View File

@ -0,0 +1,415 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ByteArrayBuffer;
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;
/* ------------------------------------------------------------ */
/**
*/
public class JavaMonitorAction extends MonitorAction
{
private final HttpClient _client;
private final String _url;
private final String _uuid;
private final String _appid;
private String _srvip;
private String _session;
/* ------------------------------------------------------------ */
/**
* @param notifier
* @param pollInterval
* @throws Exception
* @throws MalformedObjectNameException
*/
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;
_client = new HttpClient();
_client.setTimeout(60000);
_client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
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 {
ContentExchange reqEx = new ContentExchange();
reqEx.setURL(_url);
reqEx.setMethod(HttpMethods.POST);
reqEx.addRequestHeader("Connection","close");
reqStream = new ByteArrayOutputStream();
request.storeToXML(reqStream,null);
ByteArrayBuffer reqBuff = new ByteArrayBuffer(reqStream.toByteArray());
reqEx.setRequestContent(reqBuff);
_client.send(reqEx);
reqEx.waitForDone();
if (reqEx.getResponseStatus() == HttpStatus.OK_200)
{
response = new Properties();
resStream = new ByteArrayInputStream(reqEx.getResponseContentBytes());
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

@ -0,0 +1,270 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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;
/* ------------------------------------------------------------ */
/**
* 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 kjkoster <kjkoster@gmail.com>
*/
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;
}
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>();
public int getThreadsBlocked()
{
sampleThreads();
return states.get(Thread.State.BLOCKED);
}
public int getThreadsNew()
{
sampleThreads();
return states.get(Thread.State.NEW);
}
public int getThreadsTerminated()
{
sampleThreads();
return states.get(Thread.State.TERMINATED);
}
public int getThreadsTimedWaiting()
{
sampleThreads();
return states.get(Thread.State.TIMED_WAITING);
}
public int getThreadsWaiting()
{
sampleThreads();
return states.get(Thread.State.WAITING);
}
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";
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();
}
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";
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;
}
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

@ -0,0 +1,77 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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.MalformedObjectNameException;
import javax.management.ObjectName;
import org.eclipse.jetty.monitor.triggers.AttrEventTrigger;
/* ------------------------------------------------------------ */
/**
*/
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;
/* ------------------------------------------------------------ */
/**
* @param nameObject
* @param attributeName
* @param id
* @param dynamic
* @throws IllegalArgumentException
*/
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

@ -0,0 +1,56 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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
*/
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

@ -0,0 +1,34 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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 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

@ -0,0 +1,202 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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
*/
public class EventState<TYPE>
{
/* ------------------------------------------------------------ */
/**
* State
*
* Holds the state of a single {@link org.eclipse.jetty.monitor.jmx.EventTrigger event trigger}
*/
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

@ -0,0 +1,69 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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
*
* @return true to trigger an event
*/
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

@ -0,0 +1,57 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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;
/* ------------------------------------------------------------ */
/**
* ConsoleNotifier
*
* Provides a way to output notification messages to a log file
*/
public class LoggingNotifier implements EventNotifier
{
String _messageFormat;
/* ------------------------------------------------------------ */
/**
* Constructs a new notifier with specified format string
*
* @param format the {@link java.util.Formatter format string}
* @throws IllegalArgumentException
*/
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

@ -0,0 +1,174 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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
*/
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
*/
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
*/
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
*/
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

@ -0,0 +1,111 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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.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 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.dispatch(new Runnable() {
public void run()
{
try
{
if(trigger.match(timestamp))
_action.doExecute(timestamp);
}
catch (Exception ex)
{
Log.debug(ex);
}
}
});
}
}

View File

@ -0,0 +1,115 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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

@ -0,0 +1,164 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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;
/* ------------------------------------------------------------ */
/**
* 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 String _serviceUrl;
private MBeanServer _server;
private JMXConnectorServer _connectorServer;
private JMXConnector _serverConnector;
private MBeanServerConnection _serviceConnection;
/* ------------------------------------------------------------ */
/**
* Construct a loopback connection to an internal server
*
* @throws IOException
*/
public ServiceConnection()
throws IOException
{
this(null);
}
/* ------------------------------------------------------------ */
/**
* Construct a connection to specified server
*
* @param url URL of JMX server
* @throws IOException
*/
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

@ -0,0 +1,41 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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

@ -12,7 +12,7 @@
// ========================================================================
package org.eclipse.jetty.monitor;
package org.eclipse.jetty.monitor.thread;
/* ------------------------------------------------------------ */

View File

@ -12,7 +12,7 @@
// ========================================================================
package org.eclipse.jetty.monitor;
package org.eclipse.jetty.monitor.thread;
/* ------------------------------------------------------------ */

View File

@ -0,0 +1,164 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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);
}
/* ------------------------------------------------------------ */
/**
* @param trigger
*/
public void add(EventTrigger trigger)
{
_triggers.add(trigger);
}
/* ------------------------------------------------------------ */
/**
* @param triggers
*/
public void addAll(List<EventTrigger> triggers)
{
_triggers.addAll(triggers);
}
/* ------------------------------------------------------------ */
/**
* @param 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

@ -0,0 +1,129 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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

@ -0,0 +1,232 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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;
/* ------------------------------------------------------------ */
/**
* AttrEventTrigger
*
* 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.
*/
public class AttrEventTrigger<TYPE extends Comparable<TYPE>>
extends EventTrigger
{
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
* @throws IllegalArgumentException
*/
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
*/
public AttrEventTrigger(ObjectName nameObject, String attributeName)
throws IllegalArgumentException
{
if (nameObject == null)
throw new IllegalArgumentException("Object name cannot be null");
if (attributeName == null)
throw new IllegalArgumentException("Attribute name cannot be null");
_states = new ConcurrentHashMap<Long,EventState<TYPE>>();
_objectName = nameObject.toString();
_attributeName = attributeName;
_nameObject = nameObject;
}
/* ------------------------------------------------------------ */
/**
* Verify if the event trigger conditions are in the
* appropriate state for an event to be triggered.
* This event trigger uses the match(Comparable<TYPE>)
* method to compare the value of the MXBean attribute
* to the conditions specified by the subclasses.
*
* @see org.eclipse.jetty.monitor.jmx.EventTrigger#match(long)
*/
@SuppressWarnings("unchecked")
public final boolean match(long timestamp)
throws Exception
{
MBeanServerConnection serverConnection = JMXMonitor.getServiceConnection();
TYPE value = null;
try
{
int pos = _attributeName.indexOf('.');
if (pos < 0)
value = (TYPE)serverConnection.getAttribute(_nameObject,_attributeName);
else
value = getValue((CompositeData)serverConnection.getAttribute(_nameObject, _attributeName.substring(0, pos)),
_attributeName.substring(pos+1));
}
catch (Exception ex)
{
Log.debug(ex);
}
boolean result = false;
if (value != null)
{
result = match(value);
if (result || getSaveAll())
{
_states.put(timestamp,
new EventState<TYPE>(this.getID(), this.getNameString(), value));
}
}
return result;
}
/* ------------------------------------------------------------ */
/**
* Verify if the event trigger conditions are in the
* appropriate state for an event to be triggered.
* Allows subclasses to override the default behavior
* that matches every invocation of this trigger
*/
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

@ -0,0 +1,85 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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
*
* Event trigger that polls a value of an MXBean attribute and
* checks if it is equal to specified value.
*/
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
* @throws IllegalArgumentException
*/
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

@ -0,0 +1,87 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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
*
* Event trigger that polls a value of an MXBean attribute and
* checks if it is greater than specified min value.
*/
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
* @throws IllegalArgumentException
*/
public GreaterThanAttrEventTrigger(String objectName, String attributeName, TYPE min)
throws MalformedObjectNameException, IllegalArgumentException
{
super(objectName,attributeName);
if (min == null)
throw new IllegalArgumentException("Value cannot be null");
_min = min;
}
/* ------------------------------------------------------------ */
/**
* Compare the value of the MXBean attribute being polling
* to check if it is greater than the min value.
*
* @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
*/
@Override
public boolean match(Comparable<TYPE> value)
{
return (value.compareTo(_min) > 0);
}
/* ------------------------------------------------------------ */
/**
* Returns the string representation of this event trigger
* in the format "min<name".
*
* @return string representation of the event trigger
*
* @see java.lang.Object#toString()
*/
public String toString()
{
StringBuilder result = new StringBuilder();
result.append(_min);
result.append("<");
result.append(getNameString());
return result.toString();
}
}

View File

@ -0,0 +1,87 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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
*
* Event trigger that polls a value of an MXBean attribute and
* checks if it is greater than or equal to specified min value.
*/
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
* @throws IllegalArgumentException
*/
public GreaterThanOrEqualToAttrEventTrigger(String objectName, String attributeName, TYPE min)
throws MalformedObjectNameException, IllegalArgumentException
{
super(objectName,attributeName);
if (min == null)
throw new IllegalArgumentException("Value cannot be null");
_min = min;
}
/* ------------------------------------------------------------ */
/**
* Compare the value of the MXBean attribute being polling
* to check if it is greater than or equal to the min value.
*
* @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
*/
@Override
public boolean match(Comparable<TYPE> value)
{
return (value.compareTo(_min) >= 0);
}
/* ------------------------------------------------------------ */
/**
* Returns the string representation of this event trigger
* in the format "min<=name".
*
* @return string representation of the event trigger
*
* @see java.lang.Object#toString()
*/
public String toString()
{
StringBuilder result = new StringBuilder();
result.append(_min);
result.append("<=");
result.append(getNameString());
return result.toString();
}
}

View File

@ -0,0 +1,87 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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
*
* Event trigger that polls a value of an MXBean attribute and
* checks if it is greater than specified max value.
*/
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
* @throws IllegalArgumentException
*/
public LessThanAttrEventTrigger(String objectName, String attributeName, TYPE max)
throws MalformedObjectNameException, IllegalArgumentException
{
super(objectName,attributeName);
if (max == null)
throw new IllegalArgumentException("Value cannot be null");
_max = max;
}
/* ------------------------------------------------------------ */
/**
* Compare the value of the MXBean attribute being polling
* to check if it is less than the min value.
*
* @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
*/
@Override
public boolean match(Comparable<TYPE> value)
{
return (value.compareTo(_max) < 0);
}
/* ------------------------------------------------------------ */
/**
* Returns the string representation of this event trigger
* in the format "name<max".
*
* @return string representation of the event trigger
*
* @see java.lang.Object#toString()
*/
public String toString()
{
StringBuilder result = new StringBuilder();
result.append(getNameString());
result.append("<");
result.append(_max);
return result.toString();
}
}

View File

@ -0,0 +1,87 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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
*
* Event trigger that polls a value of an MXBean attribute and
* checks if it is less than or equal to specified max value.
*/
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
* @throws IllegalArgumentException
*/
public LessThanOrEqualToAttrEventTrigger(String objectName, String attributeName, TYPE max)
throws MalformedObjectNameException, IllegalArgumentException
{
super(objectName,attributeName);
if (max == null)
throw new IllegalArgumentException("Value cannot be null");
_max = max;
}
/* ------------------------------------------------------------ */
/**
* Compare the value of the MXBean attribute being polling
* to check if it is less than or equal to the max value.
*
* @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
*/
@Override
public boolean match(Comparable<TYPE> value)
{
return (value.compareTo(_max) <= 0);
}
/* ------------------------------------------------------------ */
/**
* Returns the string representation of this event trigger
* in the format "name<=max".
*
* @return string representation of the event trigger
*
* @see java.lang.Object#toString()
*/
public String toString()
{
StringBuilder result = new StringBuilder();
result.append(getNameString());
result.append("<=");
result.append(_max);
return result.toString();
}
}

View File

@ -0,0 +1,133 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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

@ -0,0 +1,96 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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
*
* 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.
*/
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
* @throws IllegalArgumentException
*/
public RangeAttrEventTrigger(String objectName, String attributeName,TYPE min, TYPE max)
throws MalformedObjectNameException, IllegalArgumentException
{
super(objectName,attributeName);
if (min == null)
throw new IllegalArgumentException("Value cannot be null");
if (max == null)
throw new IllegalArgumentException("Value cannot be null");
_min = min;
_max = max;
}
/* ------------------------------------------------------------ */
/**
* Compare the value of the MXBean attribute being polling
* to check if it is in a range from specified min value to
* specified max value.
*
* @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
*/
@Override
public boolean match(Comparable<TYPE> value)
{
return (value.compareTo(_min) > 0) &&(value.compareTo(_max) < 0);
}
/* ------------------------------------------------------------ */
/**
* Returns the string representation of this event trigger
* in the format "min<name<max".
*
* @return string representation of the event trigger
*
* @see java.lang.Object#toString()
*/
public String toString()
{
StringBuilder result = new StringBuilder();
result.append(_min);
result.append("<");
result.append(getNameString());
result.append("<");
result.append(_max);
return result.toString();
}
}

View File

@ -0,0 +1,96 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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
*
* 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.
*/
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
* @throws IllegalArgumentException
*/
public RangeInclAttrEventTrigger(String objectName, String attributeName,TYPE min, TYPE max)
throws MalformedObjectNameException, IllegalArgumentException
{
super(objectName,attributeName);
if (min == null)
throw new IllegalArgumentException("Value cannot be null");
if (max == null)
throw new IllegalArgumentException("Value cannot be null");
_min = min;
_max = max;
}
/* ------------------------------------------------------------ */
/**
* Compare the value of the MXBean attribute being polling
* to check if it is in a range from specified min value to
* specified max value including the range bounds.
*
* @see org.eclipse.jetty.monitor.triggers.AttrEventTrigger#match(java.lang.Comparable)
*/
@Override
public boolean match(Comparable<TYPE> value)
{
return (value.compareTo(_min) >= 0) &&(value.compareTo(_max) <= 0);
}
/* ------------------------------------------------------------ */
/**
* Returns the string representation of this event trigger
* in the format "min<=name<=max".
*
* @return string representation of the event trigger
*
* @see java.lang.Object#toString()
*/
public String toString()
{
StringBuilder result = new StringBuilder();
result.append(_min);
result.append("<=");
result.append(getNameString());
result.append("<=");
result.append(_max);
return result.toString();
}
}

View File

@ -0,0 +1,12 @@
JavaMonitorTools: Retrieves additional information required by java-monitor
DeadlockStacktraces: RO:Detailed report on the deadlocked threads.
ThreadsNew: RO:Number of new threads
ThreadsRunnable: RO:Number of runnable threads
ThreadsBlocked: RO:Number of blocked threads
ThreadsWaiting: RO:Number of waiting threads
ThreadsTimedWaiting: RO:Number of sleeping and waiting threads
ThreadsTerminated: RO:Number of terminated threads
CacheSeconds: RO:Amount of time successful DNS queries are cached for
CacheTweakedFrom: RO:Cache policy for successful DNS lookups was changed from the hard-coded default
CacheNegativeSeconds: RO:Amount of time failed DNS queries are cached for
CacheNegativeTweakedFrom: RO:Cache policy for failed DNS lookups was changed from the hard-coded default

View File

@ -0,0 +1,509 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.client.security.SimpleRealmResolver;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.monitor.JMXMonitor;
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.EventTrigger;
import org.eclipse.jetty.monitor.jmx.MonitorAction;
import org.eclipse.jetty.monitor.jmx.EventState.TriggerState;
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.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.log.Log;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
*/
public class AttrEventTriggerTest
{
private Server _server;
private TestHandler _handler;
private RequestCounter _counter;
private JMXMonitor _monitor;
private HttpClient _client;
private String _requestUrl;
@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();
SelectChannelConnector connector = new SelectChannelConnector();
_server.addConnector(connector);
_handler = new TestHandler();
_server.setHandler(_handler);
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
MBeanContainer mBeanContainer = new MBeanContainer(mBeanServer);
mBeanContainer.addBean(Log.getLog());
_counter = _handler.getRequestCounter();
mBeanContainer.addBean(_counter);
_server.addBean(mBeanContainer);
_server.getContainer().addEventListener(mBeanContainer);
_server.start();
startClient(null);
_monitor = new JMXMonitor();
int port = _server.getConnectors()[0].getLocalPort();
_requestUrl = "http://localhost:"+port+ "/";
}
@After
public void tearDown()
throws Exception
{
stopClient();
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
{
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 (responseStatus == HttpStatus.OK_200)
{
content = getExchange.getResponseContent();
}
assertEquals(HttpStatus.OK_200,responseStatus);
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

@ -0,0 +1,163 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.monitor.JMXMonitor;
import org.eclipse.jetty.toolchain.test.JettyDistro;
import org.eclipse.jetty.toolchain.test.PropertyFlag;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.thread.ExecutorThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
*/
public class JavaMonitorIntegrationTest
{
private static JettyDistro jetty;
@BeforeClass
public static void initJetty() throws Exception
{
PropertyFlag.assume("JAVAMONITOR");
jetty = new JettyDistro(JavaMonitorIntegrationTest.class);
jetty.delete("contexts/javadoc.xml");
jetty.overlayConfig("monitor");
jetty.start();
JMXMonitor.setServiceUrl(jetty.getJmxUrl());
}
@AfterClass
public static void shutdownJetty() throws Exception
{
if (jetty != null)
{
jetty.stop();
}
}
@Before
public void setUp()
throws Exception
{
Resource configRes = Resource.newClassPathResource("/org/eclipse/jetty/monitor/java-monitor-integration.xml");
XmlConfiguration xmlConfig = new XmlConfiguration(configRes.getURL());
xmlConfig.configure();
}
@Test
public void testIntegration()
throws Exception
{
final int threadCount = 100;
final long requestCount = 500;
final String requestUrl = jetty.getBaseUri().resolve("d.txt").toASCIIString();
final CountDownLatch gate = new CountDownLatch(threadCount);
ThreadPool worker = new ExecutorThreadPool(threadCount,threadCount,60,TimeUnit.SECONDS);
for (int idx=0; idx < threadCount; idx++)
{
worker.dispatch(new Runnable() {
public void run()
{
runTest(requestUrl, requestCount);
gate.countDown();
}
});
Thread.sleep(500);
}
gate.await();
assertTrue(true);
}
protected static void runTest(String requestUrl, long count)
{
HttpClient client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
try
{
client.start();
}
catch (Exception ex)
{
Log.debug(ex);
}
if (client != null)
{
Random rnd = new Random();
for (long cnt=0; cnt < count; cnt++)
{
try
{
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 (responseStatus == HttpStatus.OK_200)
{
content = getExchange.getResponseContent();
}
Thread.sleep(200);
}
catch (InterruptedException ex)
{
break;
}
catch (IOException ex)
{
Log.debug(ex);
}
}
try
{
client.stop();
}
catch (Exception ex)
{
Log.debug(ex);
}
}
}
}

View File

@ -0,0 +1,160 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.management.MBeanServerConnection;
import org.eclipse.jetty.client.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.monitor.JMXMonitor;
import org.eclipse.jetty.toolchain.jmx.JmxServiceConnection;
import org.eclipse.jetty.toolchain.test.JettyDistro;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.thread.ExecutorThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
*/
public class JmxServiceTest
{
private static JettyDistro jetty;
@BeforeClass
public static void initJetty() throws Exception
{
jetty = new JettyDistro(JmxServiceTest.class);
jetty.delete("contexts/javadoc.xml");
jetty.overlayConfig("monitor");
jetty.start();
JMXMonitor.setServiceUrl(jetty.getJmxUrl());
}
@AfterClass
public static void shutdownJetty() throws Exception
{
if (jetty != null)
{
jetty.stop();
}
}
@Before
public void setUp()
throws Exception
{
Resource configRes = Resource.newClassPathResource("/org/eclipse/jetty/monitor/jetty-monitor-service.xml");
XmlConfiguration xmlConfig = new XmlConfiguration(configRes.getURL());
xmlConfig.configure();
}
@Test
public void testThreadPoolMXBean()
throws Exception
{
final int threadCount = 100;
final long requestCount = 100;
final String requestUrl = jetty.getBaseUri().resolve("d.txt").toASCIIString();
final CountDownLatch gate = new CountDownLatch(threadCount);
ThreadPool worker = new ExecutorThreadPool(threadCount,threadCount,60,TimeUnit.SECONDS);
for (int idx=0; idx < threadCount; idx++)
{
worker.dispatch(new Runnable() {
public void run()
{
runTest(requestUrl, requestCount);
gate.countDown();
}
});
Thread.sleep(100);
}
gate.await();
assertTrue(true);
}
protected static void runTest(String requestUrl, long count)
{
HttpClient client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
try
{
client.start();
}
catch (Exception ex)
{
Log.debug(ex);
}
if (client != null)
{
for (long cnt=0; cnt < count; cnt++)
{
try
{
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 (responseStatus == HttpStatus.OK_200)
{
content = getExchange.getResponseContent();
}
Thread.sleep(100);
}
catch (InterruptedException ex)
{
break;
}
catch (IOException ex)
{
Log.debug(ex);
}
}
try
{
client.stop();
}
catch (Exception ex)
{
Log.debug(ex);
}
}
}
}

View File

@ -0,0 +1,179 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import javax.management.MBeanServerConnection;
import org.eclipse.jetty.client.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.monitor.JMXMonitor;
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.EventTrigger;
import org.eclipse.jetty.monitor.jmx.MonitorAction;
import org.eclipse.jetty.monitor.triggers.GreaterThanAttrEventTrigger;
import org.eclipse.jetty.monitor.triggers.LessThanOrEqualToAttrEventTrigger;
import org.eclipse.jetty.monitor.triggers.OrEventTrigger;
import org.eclipse.jetty.toolchain.jmx.JmxServiceConnection;
import org.eclipse.jetty.toolchain.test.JettyDistro;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.thread.ExecutorThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
*/
public class ProgramConfigTest
{
private static JettyDistro jetty;
@BeforeClass
public static void initJetty() throws Exception
{
jetty = new JettyDistro(ProgramConfigTest.class);
jetty.delete("contexts/javadoc.xml");
jetty.overlayConfig("monitor");
jetty.start();
JMXMonitor.setServiceUrl(jetty.getJmxUrl());
}
@AfterClass
public static void shutdownJetty() throws Exception
{
if (jetty != null)
{
jetty.stop();
}
}
@Test
public void testThreadPoolMXBean()
throws Exception
{
int testRangeLow = 4;
int testRangeHigh = 7;
LessThanOrEqualToAttrEventTrigger<Integer> trigger1 =
new LessThanOrEqualToAttrEventTrigger<Integer>("org.eclipse.jetty.util.thread:type=queuedthreadpool,id=0", "idleThreads",
testRangeLow);
GreaterThanAttrEventTrigger<Integer> trigger2 =
new GreaterThanAttrEventTrigger<Integer>("org.eclipse.jetty.util.thread:type=queuedthreadpool,id=0", "idleThreads",
testRangeHigh);
OrEventTrigger trigger = new OrEventTrigger(trigger1, trigger2);
EventNotifier notifier = new ConsoleNotifier("%s");
final AtomicLong counter = new AtomicLong();
MonitorAction action = new MonitorAction(trigger, notifier, 500) {
@Override
public void execute(EventTrigger trigger, EventState<?> state, long timestamp)
{
System.out.println(counter.incrementAndGet());
}
};
JMXMonitor.addMonitorActions(action);
final int threadCount = 100;
final long requestCount = 100;
final String requestUrl = jetty.getBaseUri().resolve("d.txt").toASCIIString();
final CountDownLatch gate = new CountDownLatch(threadCount);
ThreadPool worker = new ExecutorThreadPool(threadCount,threadCount,60,TimeUnit.SECONDS);
for (int idx=0; idx < threadCount; idx++)
{
worker.dispatch(new Runnable() {
public void run()
{
runTest(requestUrl, requestCount);
gate.countDown();
}
});
Thread.sleep(100);
}
gate.await();
JMXMonitor.removeMonitorActions(action);
assertTrue(true);
}
protected static void runTest(String requestUrl, long count)
{
HttpClient client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
try
{
client.start();
}
catch (Exception ex)
{
Log.debug(ex);
}
if (client != null)
{
for (long cnt=0; cnt < count; cnt++)
{
try
{
ContentExchange getExchange = new ContentExchange();
getExchange.setURL(requestUrl);
getExchange.setMethod(HttpMethods.GET);
client.send(getExchange);
getExchange.waitForDone();
String content = "";
int responseStatus = getExchange.getResponseStatus();
if (responseStatus == HttpStatus.OK_200)
{
content = getExchange.getResponseContent();
}
Thread.sleep(100);
}
catch (InterruptedException ex)
{
break;
}
catch (IOException ex)
{
Log.debug(ex);
}
}
try
{
client.stop();
}
catch (Exception ex)
{
Log.debug(ex);
}
}
}
}

View File

@ -0,0 +1,35 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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;
public class RequestCounter
{
public long _counter;
public synchronized long getCounter()
{
return _counter;
}
public synchronized void increment()
{
_counter++;
}
public synchronized void reset()
{
_counter = 0;
}
}

View File

@ -0,0 +1,159 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// 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.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.monitor.JMXMonitor;
import org.eclipse.jetty.toolchain.test.JettyDistro;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.thread.ExecutorThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
*/
public class XmlConfigTest
{
private static JettyDistro jetty;
@BeforeClass
public static void initJetty() throws Exception
{
jetty = new JettyDistro(XmlConfigTest.class);
jetty.delete("contexts/javadoc.xml");
jetty.overlayConfig("monitor");
jetty.start();
JMXMonitor.setServiceUrl(jetty.getJmxUrl());
}
@AfterClass
public static void shutdownJetty() throws Exception
{
if (jetty != null)
{
jetty.stop();
}
}
@Before
public void setUp()
throws Exception
{
Resource configRes = Resource.newClassPathResource("/org/eclipse/jetty/monitor/jetty-monitor-test.xml");
XmlConfiguration xmlConfig = new XmlConfiguration(configRes.getURL());
xmlConfig.configure();
}
@Test
public void testThreadPoolMXBean()
throws Exception
{
final int threadCount = 100;
final long requestCount = 100;
final String requestUrl = jetty.getBaseUri().resolve("d.txt").toASCIIString();
final CountDownLatch gate = new CountDownLatch(threadCount);
ThreadPool worker = new ExecutorThreadPool(threadCount,threadCount,60,TimeUnit.SECONDS);
for (int idx=0; idx < threadCount; idx++)
{
worker.dispatch(new Runnable() {
public void run()
{
runTest(requestUrl, requestCount);
gate.countDown();
}
});
Thread.sleep(100);
}
gate.await();
assertTrue(true);
}
protected static void runTest(String requestUrl, long count)
{
HttpClient client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
try
{
client.start();
}
catch (Exception ex)
{
Log.debug(ex);
}
if (client != null)
{
Random rnd = new Random();
for (long cnt=0; cnt < count; cnt++)
{
try
{
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 (responseStatus == HttpStatus.OK_200)
{
content = getExchange.getResponseContent();
}
Thread.sleep(100);
}
catch (InterruptedException ex)
{
break;
}
catch (IOException ex)
{
Log.debug(ex);
}
}
try
{
client.stop();
}
catch (Exception ex)
{
Log.debug(ex);
}
}
}
}

View File

@ -0,0 +1,82 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!-- ============================================================================ -->
<!-- To correctly start Jetty with JMX module enabled, this configuration -->
<!-- file must appear first in the list of the configuration files. -->
<!-- The simplest way to achieve this is to add etc/jetty-jmx.xml as the -->
<!-- first file in configuration file list at the end of start.ini file. -->
<!-- ============================================================================ -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Initialize an mbean server -->
<!-- =========================================================== -->
<Call id="MBeanServer" class="java.lang.management.ManagementFactory"
name="getPlatformMBeanServer" />
<!-- =========================================================== -->
<!-- Initialize the Jetty MBean container -->
<!-- =========================================================== -->
<New id="MBeanContainer" class="org.eclipse.jetty.jmx.MBeanContainer">
<Arg>
<Ref id="MBeanServer" />
</Arg>
</New>
<!-- Add to the Server to listen for object events -->
<Get id="Container" name="container">
<Call name="addEventListener">
<Arg>
<Ref id="MBeanContainer" />
</Arg>
</Call>
</Get>
<!-- Add to the Server as a lifecycle -->
<!-- Only do this if you know you will only have a single jetty server -->
<Call name="addBean">
<Arg>
<Ref id="MBeanContainer" />
</Arg>
</Call>
<!-- Add the static log -->
<Get id="Logger" class="org.eclipse.jetty.util.log.Log" name="log" />
<Ref id="MBeanContainer">
<Call name="addBean">
<Arg>
<Ref id="Logger" />
</Arg>
</Call>
</Ref>
<!-- In order to connect to the JMX server remotely from a different
process, possibly running on a different host, Jetty JMX module
can create a remote JMX connector.
-->
<!-- Optionally add a remote JMX connector. The parameters of the constructor
below specify the JMX service URL, and the object name string for the
connector server bean. The parameters of the JMXServiceURL constructor
specify the protocol that clients will use to connect to the remote JMX
connector (RMI), the hostname of the server (local hostname), port number
(automatically assigned), and the URL path. Note that URL path contains
the RMI registry hostname and port number, that may need to be modified
in order to comply with the firewall requirements.
-->
<New id="ConnectorServer" class="org.eclipse.jetty.jmx.ConnectorServer">
<Arg>
<New class="javax.management.remote.JMXServiceURL">
<Arg type="java.lang.String">rmi</Arg>
<Arg type="java.lang.String" />
<Arg type="java.lang.Integer">0</Arg>
<Arg type="java.lang.String">/jndi/rmi://localhost:0/jettyjmx</Arg>
</New>
</Arg>
<Arg>org.eclipse.jetty:name=rmiconnectorserver</Arg>
<Call name="start" />
</New>
</Configure>

View File

@ -0,0 +1,7 @@
OPTIONS=Server,jsp,jmx,resources,websocket,ext
etc/jetty-jmx.xml
etc/jetty.xml
etc/jetty-deploy.xml
etc/jetty-webapps.xml
etc/jetty-contexts.xml
etc/jetty-testrealm.xml

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!--
// ========================================================================
// Copyright (c) Webtide LLC
//
// 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.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
-->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!--
<Call id="MBeanServer" class="java.lang.management.ManagementFactory" name="getPlatformMBeanServer">
<Call name="registerMBean">
<Arg><New class="com.javamonitor.mbeans.DNSCachePolicy" /></Arg>
<Arg>
<New class="javax.management.ObjectName">
<Arg>com.javamonitor:type=DNSCachePolicy</Arg>
</New>
</Arg>
</Call>
<Call name="registerMBean">
<Arg><New class="com.javamonitor.mbeans.Threading" /></Arg>
<Arg>
<New class="javax.management.ObjectName">
<Arg>com.javamonitor:type=Threading</Arg>
</New>
</Arg>
</Call>
</Call>
-->
<Call id="JMXMonitor" class="org.eclipse.jetty.monitor.JMXMonitor" name="getInstance">
<Call name="addActions">
<Arg>
<Array type="org.eclipse.jetty.monitor.jmx.MonitorAction">
<Item>
<New id="MonitorAction" class="org.eclipse.jetty.monitor.integration.JavaMonitorAction">
<Arg />
<Arg>http://194.109.206.51/lemongrass/1.1/push</Arg>
<Arg>57e48e79-f0e6-4909-a6da-e8c1267cbf49</Arg>
<Arg>8080</Arg>
<Arg type="java.lang.Integer">15000</Arg>
</New>
</Item>
</Array>
</Arg>
</Call>
</Call>
</Configure>

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!--
// ========================================================================
// Copyright (c) Webtide LLC
//
// 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.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
-->
<Configure id="Monitor" class="org.eclipse.jetty.monitor.JMXMonitor">
<Call name="setUrl">
<Arg>service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jettyjmx</Arg>
</Call>
<Call name="addActions">
<Arg>
<Array type="org.eclipse.jetty.monitor.jmx.MonitorAction">
<Item>
<New class="org.eclipse.jetty.monitor.jmx.SimpleAction">
<Arg>
<New class="org.eclipse.jetty.monitor.triggers.OrEventTrigger">
<Arg>
<Array type="org.eclipse.jetty.monitor.jmx.EventTrigger">
<Item>
<New
class="org.eclipse.jetty.monitor.triggers.LessThanOrEqualToAttrEventTrigger">
<Arg>org.eclipse.jetty.util.thread:type=queuedthreadpool,id=0
</Arg>
<Arg>idleThreads</Arg>
<Arg type="java.lang.Integer">4</Arg>
</New>
</Item>
<Item>
<New
class="org.eclipse.jetty.monitor.triggers.GreaterThanAttrEventTrigger">
<Arg>org.eclipse.jetty.util.thread:type=queuedthreadpool,id=0
</Arg>
<Arg>idleThreads</Arg>
<Arg type="java.lang.Integer">7</Arg>
</New>
</Item>
</Array>
</Arg>
</New>
</Arg>
<Arg>
<New class="org.eclipse.jetty.monitor.jmx.ConsoleNotifier">
<Arg>%s</Arg>
</New>
</Arg>
<Arg type="java.lang.Long">500</Arg>
</New>
</Item>
</Array>
</Arg>
</Call>
</Configure>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!--
// ========================================================================
// Copyright (c) Webtide LLC
//
// 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.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
-->
<Configure id="Monitor" class="org.eclipse.jetty.monitor.JMXMonitor">
<Call name="addActions">
<Arg>
<Array type="org.eclipse.jetty.monitor.jmx.MonitorAction">
<Item>
<New class="org.eclipse.jetty.monitor.jmx.SimpleAction">
<Arg>
<New class="org.eclipse.jetty.monitor.triggers.OrEventTrigger">
<Arg>
<Array type="org.eclipse.jetty.monitor.jmx.EventTrigger">
<Item>
<New
class="org.eclipse.jetty.monitor.triggers.LessThanOrEqualToAttrEventTrigger">
<Arg>org.eclipse.jetty.util.thread:type=queuedthreadpool,id=0
</Arg>
<Arg>idleThreads</Arg>
<Arg type="java.lang.Integer">4</Arg>
</New>
</Item>
<Item>
<New
class="org.eclipse.jetty.monitor.triggers.GreaterThanAttrEventTrigger">
<Arg>org.eclipse.jetty.util.thread:type=queuedthreadpool,id=0
</Arg>
<Arg>idleThreads</Arg>
<Arg type="java.lang.Integer">7</Arg>
</New>
</Item>
</Array>
</Arg>
</New>
</Arg>
<Arg>
<New class="org.eclipse.jetty.monitor.jmx.ConsoleNotifier">
<Arg>%s</Arg>
</New>
</Arg>
<Arg type="java.lang.Long">500</Arg>
</New>
</Item>
</Array>
</Arg>
</Call>
</Configure>

View File

@ -0,0 +1,3 @@
RequestCounter: Request counter
counter: current value of the counter
increment(): increment the counter