From 790d2bb53833817eeea30c8de3240c40b53a605d Mon Sep 17 00:00:00 2001 From: Luck Date: Wed, 17 Apr 2019 18:35:32 +0100 Subject: Add CPU and disk usage to health command --- .../spark/common/command/modules/HealthModule.java | 53 +++++++++++++- .../lucko/spark/common/monitor/cpu/CpuMonitor.java | 85 ++++++++++++++++++++++ 2 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 spark-common/src/main/java/me/lucko/spark/common/monitor/cpu/CpuMonitor.java (limited to 'spark-common/src/main/java/me/lucko/spark/common') diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/modules/HealthModule.java b/spark-common/src/main/java/me/lucko/spark/common/command/modules/HealthModule.java index 8e4178a..66cee54 100644 --- a/spark-common/src/main/java/me/lucko/spark/common/command/modules/HealthModule.java +++ b/spark-common/src/main/java/me/lucko/spark/common/command/modules/HealthModule.java @@ -24,13 +24,18 @@ import com.google.common.base.Strings; import me.lucko.spark.common.command.Command; import me.lucko.spark.common.command.CommandModule; import me.lucko.spark.common.command.tabcomplete.TabCompleter; +import me.lucko.spark.common.monitor.cpu.CpuMonitor; import me.lucko.spark.common.monitor.tick.TpsCalculator; +import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryType; import java.lang.management.MemoryUsage; +import java.nio.file.FileStore; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -55,7 +60,7 @@ public class HealthModule implements CommandModule { ); consumer.accept(Command.builder() - .aliases("healthreport", "health") + .aliases("healthreport", "health", "ht") .argumentUsage("memory", null) .executor((platform, sender, resp, arguments) -> { resp.replyPrefixed("&7Generating server health report..."); @@ -111,6 +116,38 @@ public class HealthModule implements CommandModule { } } + double systemCpuLoad = CpuMonitor.getSystemCpuLoad(); + double processCpuLoad = CpuMonitor.getProcessCpuLoad(); + + if (systemCpuLoad >= 0 || processCpuLoad >= 0) { + report.add("&8&l>&6 CPU usage: "); + + if (systemCpuLoad >= 0) { + report.add(" &7System: &a" + percent(systemCpuLoad, 1.0d)); + report.add(" " + generateCpuUsageDiagram(systemCpuLoad, 40)); + report.add(""); + } + if (processCpuLoad >= 0) { + report.add(" &7Process: &a" + percent(processCpuLoad, 1.0d)); + report.add(" " + generateCpuUsageDiagram(processCpuLoad, 40)); + report.add(""); + } + } + + try { + FileStore fileStore = Files.getFileStore(Paths.get(".")); + long totalSpace = fileStore.getTotalSpace(); + long usedSpace = totalSpace - fileStore.getUsableSpace(); + + report.add("&8&l>&6 Disk usage: "); + report.add(" &f" + formatBytes(usedSpace) + " &7/ &f" + formatBytes(totalSpace) + + " &7(&a" + percent(usedSpace, totalSpace) + "&7)"); + report.add(" " + generateDiskUsageDiagram(usedSpace, totalSpace, 40)); + report.add(""); + } catch (IOException e) { + e.printStackTrace(); + } + report.forEach(resp::reply); }); }) @@ -170,6 +207,20 @@ public class HealthModule implements CommandModule { return "&8[" + line + "&8]"; } + private static String generateCpuUsageDiagram(double usage, int length) { + int usedChars = (int) ((usage * length)); + + String line = "&7" + Strings.repeat("/", usedChars) + Strings.repeat(" ", length - usedChars); + return "&8[" + line + "&8]"; + } + + private static String generateDiskUsageDiagram(double used, double max, int length) { + int usedChars = (int) ((used * length) / max); + + String line = "&7" + Strings.repeat("/", usedChars) + Strings.repeat(" ", length - usedChars); + return "&8[" + line + "&8]"; + } + private static String formatBytes(long bytes) { if (bytes == 0) { return "0 bytes"; diff --git a/spark-common/src/main/java/me/lucko/spark/common/monitor/cpu/CpuMonitor.java b/spark-common/src/main/java/me/lucko/spark/common/monitor/cpu/CpuMonitor.java new file mode 100644 index 0000000..20d71ef --- /dev/null +++ b/spark-common/src/main/java/me/lucko/spark/common/monitor/cpu/CpuMonitor.java @@ -0,0 +1,85 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package me.lucko.spark.common.monitor.cpu; + +import javax.management.JMX; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import java.lang.management.ManagementFactory; + +public final class CpuMonitor { + private CpuMonitor() {} + + /** The object name of the com.sun.management.OperatingSystemMXBean */ + private static final String OPERATING_SYSTEM_BEAN = "java.lang:type=OperatingSystem"; + + private static OperatingSystemMXBean getBean() { + try { + MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer(); + ObjectName diagnosticBeanName = ObjectName.getInstance(OPERATING_SYSTEM_BEAN); + return JMX.newMXBeanProxy(beanServer, diagnosticBeanName, OperatingSystemMXBean.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * 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 getSystemCpuLoad() { + return getBean().getSystemCpuLoad(); + } + + /** + * 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 getProcessCpuLoad() { + return getBean().getProcessCpuLoad(); + } + + public interface OperatingSystemMXBean { + double getSystemCpuLoad(); + double getProcessCpuLoad(); + } + +} -- cgit