package com.google.dart.engine.utilities.instrumentation;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.reflect.Method;
/**
* The class {@code HealthReporter} acts as a general mechanism for reporting system state
* information to the instrumentation system
*/
public class HealthUtils {
//Copied from org.eclipse.ui.internal.HeapStatus
public static long getMaxMem() {
long max = Long.MAX_VALUE;
try {
// Must use reflect to allow compilation against JCL/Foundation
Method maxMemMethod = Runtime.class.getMethod("maxMemory", new Class[0]); //$NON-NLS-1$
Object o = maxMemMethod.invoke(Runtime.getRuntime(), new Object[0]);
if (o instanceof Long) {
max = ((Long) o).longValue();
}
} catch (Exception e) {
// ignore if method missing or if there are other failures trying to determine the max
}
return max;
}
public static void logMemory(InstrumentationBuilder instrumentation) {
instrumentation.metric("MexMemory-FeedbackUtils", getMaxMem());
instrumentation.metric("TotalMemory", Runtime.getRuntime().totalMemory());
instrumentation.metric("FreeMemory", Runtime.getRuntime().freeMemory());
}
/**
* Log data about threads to the provided instrumentation builder
*
* @param instrumentation builder to log data to
*/
public static void logThreads(InstrumentationBuilder instrumentation) {
java.lang.management.ThreadMXBean th = ManagementFactory.getThreadMXBean();
ThreadInfo[] thInfos = th.getThreadInfo(th.getAllThreadIds(), Integer.MAX_VALUE);
instrumentation.metric("threads-count", thInfos.length);
for (ThreadInfo thInfo : thInfos) {
if (thInfo == null) {
instrumentation.metric("Thread-Name", "<unknown>");
continue;
}
instrumentation.metric("Thread-Name", thInfo.getThreadName());
instrumentation.metric("Thread-ID", thInfo.getThreadId());
instrumentation.metric("Thread-State", thInfo.getThreadState().toString());
instrumentation.metric("Blocked-Count", thInfo.getBlockedCount());
instrumentation.metric("Blocked-Time", thInfo.getBlockedTime());
instrumentation.metric("Waited-Count", thInfo.getWaitedCount());
instrumentation.metric("Waited-Time", thInfo.getWaitedTime());
instrumentation.data(
"Thread-ST",
Base64.encodeBytes(stackTraceToString(thInfo.getStackTrace()).getBytes()));
}
}
/**
* Report the health state of the editor to instrumentation The method can be run on any thread
* and will return immediately, performing all of its work async
*
* @param reason what was the cause of the health check being reported
*/
public static void ReportHealth(final String reason) {
//Async create and dispatch the thread
new Thread() {
@Override
public void run() {
ReportHealthImpl(reason);
}
}.start();
}
/**
* Health reporter implementation, this must be implemented so that it can run on any thread
*
* @param reason
*/
private static void ReportHealthImpl(String reason) {
InstrumentationBuilder instrumentation = Instrumentation.builder("HealthReport");
try {
instrumentation.metric("Reason", reason);
logMemory(instrumentation);
logThreads(instrumentation);
} finally {
instrumentation.log();
}
}
private static String stackTraceToString(StackTraceElement[] elements) {
StringBuilder sb = new StringBuilder();
for (StackTraceElement element : elements) {
sb.append(element.toString());
sb.append("\n");
}
return sb.toString();
}
}