package org.act.tstream.metric;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import com.codahale.metrics.Gauge;
public class MetricJstack implements Gauge<String> {
private String getTaskName(long id, String name) {
if (name == null) {
return Long.toString(id);
}
return id + " (" + name + ")";
}
public String dumpThread() throws Exception {
StringBuilder writer = new StringBuilder();
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
boolean contention = threadMXBean.isThreadContentionMonitoringEnabled();
long[] threadIds = threadMXBean.getAllThreadIds();
writer.append(threadIds.length + " active threads:");
for (long tid : threadIds) {
writer.append(tid).append(" ");
}
writer.append("\n");
long[] deadLockTids = threadMXBean.findDeadlockedThreads();
if (deadLockTids != null) {
writer.append(threadIds.length + " deadlocked threads:");
for (long tid : deadLockTids) {
writer.append(tid).append(" ");
}
writer.append("\n");
}
long[] deadLockMonitorTids = threadMXBean
.findMonitorDeadlockedThreads();
if (deadLockMonitorTids != null) {
writer.append(threadIds.length + " deadlocked monitor threads:");
for (long tid : deadLockMonitorTids) {
writer.append(tid).append(" ");
}
writer.append("\n");
}
for (long tid : threadIds) {
ThreadInfo info = threadMXBean
.getThreadInfo(tid, Integer.MAX_VALUE);
if (info == null) {
writer.append(" Inactive").append("\n");
continue;
}
writer.append(
"Thread "
+ getTaskName(info.getThreadId(),
info.getThreadName()) + ":").append("\n");
Thread.State state = info.getThreadState();
writer.append(" State: " + state).append("\n");
writer.append(" Blocked count: " + info.getBlockedCount()).append(
"\n");
writer.append(" Waited count: " + info.getWaitedCount()).append(
"\n");
writer.append(" Cpu time:")
.append(threadMXBean.getThreadCpuTime(tid) / 1000000)
.append("ms").append("\n");
writer.append(" User time:")
.append(threadMXBean.getThreadUserTime(tid) / 1000000)
.append("ms").append("\n");
if (contention) {
writer.append(" Blocked time: " + info.getBlockedTime())
.append("\n");
writer.append(" Waited time: " + info.getWaitedTime()).append(
"\n");
}
if (state == Thread.State.WAITING) {
writer.append(" Waiting on " + info.getLockName())
.append("\n");
} else if (state == Thread.State.BLOCKED) {
writer.append(" Blocked on " + info.getLockName())
.append("\n");
writer.append(
" Blocked by "
+ getTaskName(info.getLockOwnerId(),
info.getLockOwnerName())).append("\n");
}
}
for (long tid : threadIds) {
ThreadInfo info = threadMXBean
.getThreadInfo(tid, Integer.MAX_VALUE);
if (info == null) {
writer.append(" Inactive").append("\n");
continue;
}
writer.append(
"Thread "
+ getTaskName(info.getThreadId(),
info.getThreadName()) + ": Stack").append(
"\n");
for (StackTraceElement frame : info.getStackTrace()) {
writer.append(" " + frame.toString()).append("\n");
}
}
return writer.toString();
}
@Override
public String getValue() {
try {
return dumpThread();
} catch (Exception e) {
return "Failed to get jstack thread info";
}
}
}