Merge branch 'master' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project
This commit is contained in:
commit
79a2046715
|
@ -9,3 +9,5 @@ To run ThreadMonitor on a Jetty installation that doesn't include jetty-monitor
|
|||
java -jar start.jar etc/jetty-monitor.xml
|
||||
|
||||
If running Jetty on Java VM version 1.5, the -Dcom.sun.management.jmxremote option should be added to the command lines above in order to enable the JMX agent.
|
||||
|
||||
In order to log CPU utilization for threads that are above specified threshold, you need to follow instructions inside jetty-monitor.xml configuration file.
|
|
@ -9,6 +9,13 @@
|
|||
<Set name="scanInterval">2000</Set>
|
||||
<Set name="busyThreshold">90</Set>
|
||||
<Set name="stackDepth">3</Set>
|
||||
<!-- To enable logging CPU utilization for threads above specified threshold, -->
|
||||
<!-- uncomment the following lines, changing dump interval (in milliseconds) -->
|
||||
<!-- and dump threshold (in percent) as desired. -->
|
||||
<!--
|
||||
<Set name="dumpInterval">10000</Arg>
|
||||
<Set name="dumpThreshold">1</Arg>
|
||||
-->
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
|
|
@ -19,6 +19,8 @@ import java.lang.management.ThreadInfo;
|
|||
import java.lang.management.ThreadMXBean;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -32,7 +34,9 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
||||
{
|
||||
private int _scanInterval;
|
||||
private int _dumpInterval;
|
||||
private int _busyThreshold;
|
||||
private int _dumpThreshold;
|
||||
private int _stackDepth;
|
||||
|
||||
private ThreadMXBean _threadBean;
|
||||
|
@ -70,7 +74,7 @@ public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
|||
_busyThreshold = threshold;
|
||||
_stackDepth = depth;
|
||||
|
||||
_logger = Log.getLogger(getClass().getName());
|
||||
_logger = Log.getLogger(ThreadMonitor.class.getName());
|
||||
_extInfo = new HashMap<Long, ExtThreadInfo>();
|
||||
|
||||
init();
|
||||
|
@ -89,7 +93,19 @@ public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public int getBusyThreshold()
|
||||
public int getDumpInterval()
|
||||
{
|
||||
return _dumpInterval;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setDumpInterval(int ms)
|
||||
{
|
||||
_dumpInterval = ms;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public int getBusyThreshold()
|
||||
{
|
||||
return _busyThreshold;
|
||||
}
|
||||
|
@ -100,6 +116,18 @@ public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
|||
_busyThreshold = percent;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public int getDumpThreshold()
|
||||
{
|
||||
return _dumpThreshold;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setDumpThreshold(int percent)
|
||||
{
|
||||
_dumpThreshold = percent;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public int getStackDepth()
|
||||
{
|
||||
|
@ -111,6 +139,13 @@ public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
|||
{
|
||||
_stackDepth = stackDepth;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void enableDumpAll(int ms, int percent)
|
||||
{
|
||||
setDumpInterval(ms);
|
||||
setDumpThreshold(percent);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -249,6 +284,34 @@ public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void dumpAll()
|
||||
{
|
||||
if (_extInfo.size() > 0)
|
||||
{
|
||||
List<ExtThreadInfo> sorted = new ArrayList<ExtThreadInfo>(_extInfo.values());
|
||||
Collections.sort(sorted, new Comparator<ExtThreadInfo>() {
|
||||
/* ------------------------------------------------------------ */
|
||||
public int compare(ExtThreadInfo eti1, ExtThreadInfo eti2)
|
||||
{
|
||||
return (int)Math.signum(eti2.getCpuUtilization()-eti1.getCpuUtilization());
|
||||
}
|
||||
});
|
||||
|
||||
for (ExtThreadInfo info : sorted)
|
||||
{
|
||||
ThreadInfo threadInfo = info.getThreadInfo();
|
||||
|
||||
if (info.getCpuUtilization() > 1.0f)
|
||||
{
|
||||
_logger.info(String.format("Thread %s[%d] is using %.2f of CPU", threadInfo.getThreadName(), threadInfo.getThreadId(), info.getCpuUtilization()));
|
||||
}
|
||||
|
||||
info.setDumpCpuTime(info.getLastCpuTime());
|
||||
info.setDumpSampleTime(info.getLastSampleTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -256,8 +319,9 @@ public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
|||
*/
|
||||
public void run()
|
||||
{
|
||||
long currTime;
|
||||
long lastTime = 0;
|
||||
long currTime = System.currentTimeMillis();
|
||||
long lastTime = currTime;
|
||||
long lastDumpTime = currTime;
|
||||
while (!_done)
|
||||
{
|
||||
currTime = System.currentTimeMillis();
|
||||
|
@ -285,6 +349,13 @@ public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
|||
{
|
||||
dump(threadInfo);
|
||||
}
|
||||
|
||||
if (_dumpInterval > 0 && lastTime > lastDumpTime + _dumpInterval)
|
||||
{
|
||||
lastDumpTime = lastTime;
|
||||
|
||||
dumpAll();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -321,7 +392,9 @@ public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
|||
long elapsedCpuTime = currCpuTime - currExtInfo.getLastCpuTime();
|
||||
long elapsedNanoTime = currNanoTime - currExtInfo.getLastSampleTime();
|
||||
|
||||
if (((elapsedCpuTime * 100.0) / elapsedNanoTime) > _busyThreshold)
|
||||
float cpuUtilization = Math.min((elapsedCpuTime * 100.0f) / elapsedNanoTime, 100.0f);
|
||||
currExtInfo.setCpuUtilization(cpuUtilization);
|
||||
if (cpuUtilization > _busyThreshold)
|
||||
{
|
||||
ThreadInfo currInfo = getThreadInfo(currId, Integer.MAX_VALUE);
|
||||
if (currInfo != null)
|
||||
|
@ -338,7 +411,12 @@ public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
|||
}
|
||||
else
|
||||
{
|
||||
currExtInfo = new ExtThreadInfo(currId);
|
||||
currExtInfo = new ExtThreadInfo(getThreadInfo(currId, 0));
|
||||
currExtInfo.setFirstCpuTime(currCpuTime);
|
||||
currExtInfo.setFirstSampleTime(currNanoTime);
|
||||
currExtInfo.setDumpCpuTime(currCpuTime);
|
||||
currExtInfo.setDumpSampleTime(currNanoTime);
|
||||
|
||||
_extInfo.put(Long.valueOf(currId), currExtInfo);
|
||||
}
|
||||
|
||||
|
@ -418,25 +496,72 @@ public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
|||
/* ------------------------------------------------------------ */
|
||||
private class ExtThreadInfo
|
||||
{
|
||||
private long _threadId;
|
||||
private ThreadInfo _threadInfo;
|
||||
|
||||
private long _firstCpuTime;
|
||||
private long _firstSampleTime;
|
||||
private long _lastCpuTime;
|
||||
private long _lastSampleTime;
|
||||
private long _dumpCpuTime;
|
||||
private long _dumpSampleTime;
|
||||
|
||||
private float _cpuUtilization;
|
||||
|
||||
private StackTraceElement[] _stackTrace;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ExtThreadInfo(long threadId)
|
||||
public ExtThreadInfo(ThreadInfo threadInfo)
|
||||
{
|
||||
_threadId = threadId;
|
||||
_threadInfo = threadInfo;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return thread id associated with the instance
|
||||
*/
|
||||
public long getThreadId()
|
||||
public ThreadInfo getThreadInfo()
|
||||
{
|
||||
return _threadId;
|
||||
return _threadInfo;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return the first CPU time of the thread
|
||||
*/
|
||||
public long getFirstCpuTime()
|
||||
{
|
||||
return _firstCpuTime;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set the first CPU time.
|
||||
*
|
||||
* @param ns new last CPU time
|
||||
*/
|
||||
public void setFirstCpuTime(long ns)
|
||||
{
|
||||
_firstCpuTime = ns;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return the time of first sample
|
||||
*/
|
||||
public long getFirstSampleTime()
|
||||
{
|
||||
return _firstSampleTime;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Sets the first sample time.
|
||||
*
|
||||
* @param ns the time of first sample
|
||||
*/
|
||||
public void setFirstSampleTime(long ns)
|
||||
{
|
||||
_firstSampleTime = ns;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -452,11 +577,11 @@ public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
|||
/**
|
||||
* Set the last CPU time.
|
||||
*
|
||||
* @param lastCpuTime new last CPU time
|
||||
* @param ns new last CPU time
|
||||
*/
|
||||
public void setLastCpuTime(long lastCpuTime)
|
||||
public void setLastCpuTime(long ns)
|
||||
{
|
||||
this._lastCpuTime = lastCpuTime;
|
||||
_lastCpuTime = ns;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -472,11 +597,73 @@ public class ThreadMonitor extends AbstractLifeCycle implements Runnable
|
|||
/**
|
||||
* Sets the last sample time.
|
||||
*
|
||||
* @param lastSampleTime the time of last sample
|
||||
* @param ns the time of last sample
|
||||
*/
|
||||
public void setLastSampleTime(long lastSampleTime)
|
||||
public void setLastSampleTime(long ns)
|
||||
{
|
||||
_lastSampleTime = lastSampleTime;
|
||||
_lastSampleTime = ns;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return the dump CPU time of the thread
|
||||
*/
|
||||
public long getDumpCpuTime()
|
||||
{
|
||||
return _dumpCpuTime;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set the dump CPU time.
|
||||
*
|
||||
* @param ns new dump CPU time
|
||||
*/
|
||||
public void setDumpCpuTime(long ns)
|
||||
{
|
||||
_dumpCpuTime = ns;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return the time of dump sample
|
||||
*/
|
||||
public long getDumpSampleTime()
|
||||
{
|
||||
return _dumpSampleTime;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Sets the dump sample time.
|
||||
*
|
||||
* @param ns the time of dump sample
|
||||
*/
|
||||
public void setDumpSampleTime(long ns)
|
||||
{
|
||||
_dumpSampleTime = ns;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Gets the CPU utilization.
|
||||
*
|
||||
* @return the CPU utilization percentage
|
||||
*/
|
||||
public float getCpuUtilization()
|
||||
{
|
||||
return _cpuUtilization;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Sets the CPU utilization.
|
||||
*
|
||||
* @param percentage the new CPU utilization percentage
|
||||
*/
|
||||
public void setCpuUtilization(float percentage)
|
||||
{
|
||||
_cpuUtilization = percentage;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -30,6 +30,7 @@ public class ThreadMonitorTest
|
|||
{
|
||||
public final static int DURATION=9000;
|
||||
private AtomicInteger count=new AtomicInteger(0);
|
||||
private AtomicInteger countDump=new AtomicInteger(0);
|
||||
|
||||
@Test
|
||||
public void monitorTest() throws Exception
|
||||
|
@ -43,7 +44,14 @@ public class ThreadMonitorTest
|
|||
count.incrementAndGet();
|
||||
super.dump(threads);
|
||||
}
|
||||
@Override
|
||||
protected void dumpAll()
|
||||
{
|
||||
countDump.incrementAndGet();
|
||||
super.dumpAll();
|
||||
}
|
||||
};
|
||||
monitor.enableDumpAll(2000,1);
|
||||
monitor.start();
|
||||
|
||||
Spinner spinner = new Spinner();
|
||||
|
@ -56,6 +64,7 @@ public class ThreadMonitorTest
|
|||
monitor.stop();
|
||||
|
||||
assertTrue(count.get() >= 2);
|
||||
assertTrue(countDump.get() >= 1);
|
||||
}
|
||||
|
||||
|
||||
|
|
4
pom.xml
4
pom.xml
|
@ -176,12 +176,12 @@
|
|||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<failIfNoTests>false</failIfNoTests>
|
||||
<systemProperties>
|
||||
<!--systemProperties>
|
||||
<property>
|
||||
<name>org.eclipse.jetty.io.AbstractBuffer.boundsChecking</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</systemProperties>
|
||||
</systemProperties-->
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
Loading…
Reference in New Issue