package io.pcp.parfait.timing;
import static systems.uom.unicode.CLDR.BYTE;
import static tec.uom.se.unit.MetricPrefix.MILLI;
import static tec.uom.se.unit.MetricPrefix.NANO;
import static tec.uom.se.unit.Units.SECOND;
import static tec.uom.se.AbstractUnit.ONE;
import com.google.common.collect.ImmutableList;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.util.Collection;
import javax.measure.quantity.Time;
import javax.measure.Unit;
public class StandardThreadMetrics {
private static final Unit<Time> MILLISECONDS = MILLI(SECOND);
private static final Unit<Time> NANOSECONDS = NANO(SECOND);
public static final ThreadMetric CLOCK_TIME = new AbstractThreadMetric("Elapsed time", NANOSECONDS,
"time", "Total wall time (in ms) spent executing event") {
@Override
public long getValueForThread(Thread t) {
return System.nanoTime();
}
};
public static final ThreadMetric TOTAL_CPU_TIME = new AbstractThreadMetric("Total CPU", NANOSECONDS,
"cputime", "Total CPU time (in ns) spent executing event") {
@Override
public long getValueForThread(Thread t) {
return ManagementFactory.getThreadMXBean().getThreadCpuTime(t.getId());
}
};
public static final ThreadMetric USER_CPU_TIME = new AbstractThreadMetric("User CPU", NANOSECONDS,
"utime", "User CPU time (in ns) spent executing event") {
@Override
public long getValueForThread(Thread t) {
return ManagementFactory.getThreadMXBean().getThreadUserTime(t.getId());
}
};
public static final ThreadMetric SYSTEM_CPU_TIME = new AbstractThreadMetric("System CPU", NANOSECONDS,
"stime", "System CPU time (in ns) spent executing event") {
@Override
public long getValueForThread(Thread t) {
return ManagementFactory.getThreadMXBean().getThreadCpuTime(t.getId())
- ManagementFactory.getThreadMXBean().getThreadUserTime(t.getId());
}
};
public static final ThreadMetric HEAP_BYTES = new AbstractThreadMetric("Heap Bytes", BYTE,
"heap", "Amount of Heap (in bytes) used during the event") {
@SuppressWarnings("restriction")
@Override
public long getValueForThread(Thread t) {
java.lang.management.ThreadMXBean javaLangThreadMXBean = ManagementFactory.getThreadMXBean();
if (javaLangThreadMXBean instanceof com.sun.management.ThreadMXBean) {
com.sun.management.ThreadMXBean sunThreadMXBean = (com.sun.management.ThreadMXBean) javaLangThreadMXBean;
return sunThreadMXBean.getThreadAllocatedBytes(t.getId());
}
return 0L;
}
};
public static final ThreadMetric BLOCKED_COUNT = new ThreadInfoMetric("Blocked count", ONE,
"blocked.count", "Number of times thread entered BLOCKED state during event") {
@Override
public long getValue(ThreadInfo threadInfo) {
return threadInfo.getBlockedCount();
}
};
public static final ThreadMetric BLOCKED_TIME = new ThreadInfoMetric("Blocked time", MILLISECONDS,
"blocked.time", "ms spent in BLOCKED state during event") {
@Override
public long getValue(ThreadInfo threadInfo) {
return threadInfo.getBlockedTime();
}
};
public static final ThreadMetric WAITED_COUNT = new ThreadInfoMetric("Wait count", ONE,
"waited.count",
"Number of times thread entered WAITING or TIMED_WAITING state during event") {
@Override
public long getValue(ThreadInfo threadInfo) {
return threadInfo.getWaitedCount();
}
};
public static final ThreadMetric WAITED_TIME = new ThreadInfoMetric("Wait time", MILLISECONDS,
"waited.time", "ms spent in WAITING or TIMED_WAITING state during event") {
@Override
public long getValue(ThreadInfo threadInfo) {
return threadInfo.getWaitedTime();
}
};
public static Collection<? extends ThreadMetric> defaults() {
// TOTAL_CPU_TIME is not included by default (you can get it from other places)
return ImmutableList.of(CLOCK_TIME, TOTAL_CPU_TIME, USER_CPU_TIME, SYSTEM_CPU_TIME, HEAP_BYTES,
BLOCKED_COUNT, BLOCKED_TIME, WAITED_COUNT, WAITED_TIME);
}
private static abstract class ThreadInfoMetric extends AbstractThreadMetric {
public ThreadInfoMetric(String name, Unit<?> unit, String counterSuffix, String description) {
super(name, unit, counterSuffix, description);
}
@Override
public final long getValueForThread(Thread t) {
ThreadInfo info = getThreadInfo(t);
return info == null ? 0 : getValue(info);
}
protected abstract long getValue(ThreadInfo threadInfo);
private static ThreadInfo getThreadInfo(Thread t) {
return ManagementFactory.getThreadMXBean().getThreadInfo(t.getId());
}
}
}