158 lines
6.1 KiB
Java
158 lines
6.1 KiB
Java
|
package zone.themcgamer.common;
|
||
|
|
||
|
import javax.management.JMX;
|
||
|
import javax.management.MBeanServer;
|
||
|
import javax.management.ObjectName;
|
||
|
import java.lang.management.ManagementFactory;
|
||
|
import java.math.BigDecimal;
|
||
|
import java.util.concurrent.Executors;
|
||
|
import java.util.concurrent.ScheduledExecutorService;
|
||
|
import java.util.concurrent.TimeUnit;
|
||
|
|
||
|
/**
|
||
|
* @author Lucko
|
||
|
* credits = https://github.com/lucko/spark
|
||
|
*/
|
||
|
public enum CpuMonitor {
|
||
|
;
|
||
|
|
||
|
/** The object name of the com.sun.management.OperatingSystemMXBean */
|
||
|
private static final String OPERATING_SYSTEM_BEAN = "java.lang:type=OperatingSystem";
|
||
|
/** The OperatingSystemMXBean instance */
|
||
|
private static final OperatingSystemMXBean BEAN;
|
||
|
/** The executor used to monitor & calculate rolling averages. */
|
||
|
private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor(r -> {
|
||
|
Thread thread = Executors.defaultThreadFactory().newThread(r);
|
||
|
thread.setName("core-cpu-monitor");
|
||
|
thread.setDaemon(true);
|
||
|
return thread;
|
||
|
});
|
||
|
|
||
|
// Rolling averages for system/process data
|
||
|
private static final RollingAverage SYSTEM_AVERAGE_10_SEC = new RollingAverage(10);
|
||
|
private static final RollingAverage SYSTEM_AVERAGE_1_MIN = new RollingAverage(60);
|
||
|
private static final RollingAverage SYSTEM_AVERAGE_15_MIN = new RollingAverage(60 * 15);
|
||
|
private static final RollingAverage PROCESS_AVERAGE_10_SEC = new RollingAverage(10);
|
||
|
private static final RollingAverage PROCESS_AVERAGE_1_MIN = new RollingAverage(60);
|
||
|
private static final RollingAverage PROCESS_AVERAGE_15_MIN = new RollingAverage(60 * 15);
|
||
|
|
||
|
static {
|
||
|
try {
|
||
|
MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
|
||
|
ObjectName diagnosticBeanName = ObjectName.getInstance(OPERATING_SYSTEM_BEAN);
|
||
|
BEAN = JMX.newMXBeanProxy(beanServer, diagnosticBeanName, OperatingSystemMXBean.class);
|
||
|
} catch (Exception e) {
|
||
|
throw new UnsupportedOperationException("OperatingSystemMXBean is not supported by the system", e);
|
||
|
}
|
||
|
|
||
|
// schedule rolling average calculations.
|
||
|
EXECUTOR.scheduleAtFixedRate(new RollingAverageCollectionTask(), 1, 1, TimeUnit.SECONDS);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Ensures that the static initializer has been called.
|
||
|
*/
|
||
|
@SuppressWarnings("EmptyMethod")
|
||
|
public static void ensureMonitoring() {
|
||
|
// intentionally empty
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the "recent cpu usage" for the whole system. This value is a
|
||
|
* double in the [0.0,1.0] interval. A value of 0.0 means that all CPUs
|
||
|
* were idle during the recent period of time observed, while a value
|
||
|
* of 1.0 means that all CPUs were actively running 100% of the time
|
||
|
* during the recent period being observed. All values betweens 0.0 and
|
||
|
* 1.0 are possible depending of the activities going on in the system.
|
||
|
* If the system recent cpu usage is not available, the method returns a
|
||
|
* negative value.
|
||
|
*
|
||
|
* @return the "recent cpu usage" for the whole system; a negative
|
||
|
* value if not available.
|
||
|
*/
|
||
|
public static double systemLoad() {
|
||
|
return BEAN.getSystemCpuLoad();
|
||
|
}
|
||
|
|
||
|
public static double systemLoad10SecAvg() {
|
||
|
return SYSTEM_AVERAGE_10_SEC.getAverage();
|
||
|
}
|
||
|
|
||
|
public static double systemLoad1MinAvg() {
|
||
|
return SYSTEM_AVERAGE_1_MIN.getAverage();
|
||
|
}
|
||
|
|
||
|
public static double systemLoad15MinAvg() {
|
||
|
return SYSTEM_AVERAGE_15_MIN.getAverage();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the "recent cpu usage" for the Java Virtual Machine process.
|
||
|
* This value is a double in the [0.0,1.0] interval. A value of 0.0 means
|
||
|
* that none of the CPUs were running threads from the JVM process during
|
||
|
* the recent period of time observed, while a value of 1.0 means that all
|
||
|
* CPUs were actively running threads from the JVM 100% of the time
|
||
|
* during the recent period being observed. Threads from the JVM include
|
||
|
* the application threads as well as the JVM internal threads. All values
|
||
|
* betweens 0.0 and 1.0 are possible depending of the activities going on
|
||
|
* in the JVM process and the whole system. If the Java Virtual Machine
|
||
|
* recent CPU usage is not available, the method returns a negative value.
|
||
|
*
|
||
|
* @return the "recent cpu usage" for the Java Virtual Machine process;
|
||
|
* a negative value if not available.
|
||
|
*/
|
||
|
public static double processLoad() {
|
||
|
return BEAN.getProcessCpuLoad();
|
||
|
}
|
||
|
|
||
|
public static double processLoad10SecAvg() {
|
||
|
return PROCESS_AVERAGE_10_SEC.getAverage();
|
||
|
}
|
||
|
|
||
|
public static double processLoad1MinAvg() {
|
||
|
return PROCESS_AVERAGE_1_MIN.getAverage();
|
||
|
}
|
||
|
|
||
|
public static double processLoad15MinAvg() {
|
||
|
return PROCESS_AVERAGE_15_MIN.getAverage();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Task to poll CPU loads and add to the rolling averages in the enclosing class.
|
||
|
*/
|
||
|
private static final class RollingAverageCollectionTask implements Runnable {
|
||
|
private final RollingAverage[] systemAverages = new RollingAverage[]{
|
||
|
SYSTEM_AVERAGE_10_SEC,
|
||
|
SYSTEM_AVERAGE_1_MIN,
|
||
|
SYSTEM_AVERAGE_15_MIN
|
||
|
};
|
||
|
private final RollingAverage[] processAverages = new RollingAverage[]{
|
||
|
PROCESS_AVERAGE_10_SEC,
|
||
|
PROCESS_AVERAGE_1_MIN,
|
||
|
PROCESS_AVERAGE_15_MIN
|
||
|
};
|
||
|
|
||
|
@Override
|
||
|
public void run() {
|
||
|
BigDecimal systemCpuLoad = new BigDecimal(systemLoad());
|
||
|
BigDecimal processCpuLoad = new BigDecimal(processLoad());
|
||
|
|
||
|
if (systemCpuLoad.signum() != -1) { // if value is not negative
|
||
|
for (RollingAverage average : this.systemAverages) {
|
||
|
average.add(systemCpuLoad);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (processCpuLoad.signum() != -1) { // if value is not negative
|
||
|
for (RollingAverage average : this.processAverages) {
|
||
|
average.add(processCpuLoad);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public interface OperatingSystemMXBean {
|
||
|
double getSystemCpuLoad();
|
||
|
double getProcessCpuLoad();
|
||
|
}
|
||
|
}
|