
org.rx.core.ManagementMonitor Maven / Gradle / Ivy
package org.rx.core;
import com.sun.management.HotSpotDiagnosticMXBean;
import com.sun.management.OperatingSystemMXBean;
import com.sun.management.ThreadMXBean;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.rx.bean.FlagsEnum;
import org.rx.io.Bytes;
import java.io.File;
import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.util.List;
import static org.rx.core.App.hashKey;
import static org.rx.core.Constants.PERCENT;
//JMX监控JVM,K8S监控网络,这里简单处理Thread相关
public class ManagementMonitor implements EventTarget {
@Getter
private static final ManagementMonitor instance = new ManagementMonitor();
@RequiredArgsConstructor
@Getter
public static class DiskMonitorInfo implements Serializable {
private static final long serialVersionUID = 743624611466728938L;
private final String name;
private final long usedSpace, totalSpace;
public int getUsedPercent() {
return toPercent((double) usedSpace / totalSpace);
}
public String getUsedString() {
return Bytes.readableByteSize(usedSpace);
}
public String getTotalString() {
return Bytes.readableByteSize(totalSpace);
}
}
@RequiredArgsConstructor
@Getter
public static class ThreadMonitorInfo {
private final ThreadInfo threadInfo;
private final long cpuTime;
@Override
public String toString() {
StringBuilder s = new StringBuilder(threadInfo.toString());
int i = s.indexOf("\n");
s.insert(i, String.format(" cpuTime=%s", cpuTime));
return s.toString();
}
}
@RequiredArgsConstructor
@Getter
public static class MonitorInfo implements Serializable {
private static final long serialVersionUID = -5980065718359999352L;
private final int cpuThreads;
private final double cpuLoad;
private final int liveThreadCount;
private final long usedMemory;
private final long totalMemory;
private final Linq disks;
public int getCpuLoadPercent() {
return toPercent(cpuLoad);
}
public String getCpuLoadString() {
return formatCpu(cpuLoad);
}
public int getUsedMemoryPercent() {
return toPercent((double) usedMemory / totalMemory);
}
public String getUsedMemoryString() {
return Bytes.readableByteSize(usedMemory);
}
public String getTotalMemoryString() {
return Bytes.readableByteSize(totalMemory);
}
public DiskMonitorInfo getSummedDisk() {
return disks.groupBy(p -> true, (p, x) -> new DiskMonitorInfo("/", (long) x.sum(y -> y.usedSpace), (long) x.sum(y -> y.totalSpace))).first();
}
}
public static String formatCpu(double val) {
String p = String.valueOf(val * PERCENT);
int ix = p.indexOf(".") + 1;
String percent = p.substring(0, ix) + p.charAt(ix);
return percent + "%";
}
private static int toPercent(double val) {
return (int) Math.ceil(val * PERCENT);
}
public final Delegate> onScheduled = Delegate.create(),
onCpuWarning = Delegate.create(),
onMemoryWarning = Delegate.create(),
onDiskWarning = Delegate.create();
@Setter
private int cpuWarningThreshold;
@Setter
private int memoryWarningThreshold;
@Setter
private int diskWarningThreshold;
private final OperatingSystemMXBean os = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
private final ThreadMXBean threads = (ThreadMXBean) ManagementFactory.getThreadMXBean();
private final HotSpotDiagnosticMXBean diagnostic = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
@Override
public FlagsEnum eventFlags() {
return EventFlags.DYNAMIC_ATTACH.flags(EventFlags.QUIETLY);
}
private ManagementMonitor() {
Tasks.schedulePeriod(() -> {
NEventArgs args = new NEventArgs<>(getInfo());
raiseEvent(onScheduled, args);
if (args.getValue().getCpuLoad() >= cpuWarningThreshold) {
raiseEvent(onCpuWarning, args);
}
if (args.getValue().getUsedMemoryPercent() >= memoryWarningThreshold) {
raiseEvent(onMemoryWarning, args);
}
for (DiskMonitorInfo disk : args.getValue().getDisks()) {
if (disk.getUsedPercent() >= diskWarningThreshold) {
raiseEvent(onDiskWarning, args);
}
}
}, 5000);
}
public MonitorInfo getInfo() {
long totalMemory = os.getTotalPhysicalMemorySize();
return new MonitorInfo(os.getAvailableProcessors(), os.getSystemCpuLoad(), threads.getThreadCount(),
totalMemory - os.getFreePhysicalMemorySize(), totalMemory,
Cache.getOrSet(hashKey("monitorInfo"), k -> Linq.from(File.listRoots()).select(p -> new DiskMonitorInfo(p.getPath(), p.getTotalSpace() - p.getFreeSpace(), p.getTotalSpace())), Cache.MEMORY_CACHE));
}
public ThreadInfo[] findDeadlockedThreads() {
long[] deadlockedThreads = Arrays.addAll(threads.findDeadlockedThreads(), threads.findMonitorDeadlockedThreads());
return threads.getThreadInfo(deadlockedThreads, false, false);
}
public List findTopCpuTimeThreads(int num) {
if (!threads.isThreadCpuTimeEnabled()) {
threads.setThreadCpuTimeEnabled(true);
}
Linq allThreads = Linq.from(threads.dumpAllThreads(true, true));
long[] tids = Arrays.toPrimitive(allThreads.select(ThreadInfo::getThreadId).toArray());
long[] threadCpuTime = threads.getThreadCpuTime(tids);
// long[] threadUserTime = threads.getThreadUserTime(tids);
// return allThreads.select((p, i) -> new ThreadMonitorInfo(p, threadCpuTime[i], threadUserTime[i])).orderByDescending(p -> p.cpuTime).take(num).toList();
return allThreads.select((p, i) -> new ThreadMonitorInfo(p, threadCpuTime[i])).orderByDescending(p -> p.cpuTime).take(num).toList();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy