package com.evps.common.utils; import com.sun.management.OperatingSystemMXBean; import lombok.Getter; import java.io.File; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.time.Instant; import java.time.ZoneId; import java.util.HashMap; import java.util.Map; @Getter public class SystemHealth { private String osName = System.getProperty("os.name"); private String osVersion = System.getProperty("os.version"); private int cpuCores = Runtime.getRuntime().availableProcessors(); private long maxMemory = Runtime.getRuntime().maxMemory(); private long totalMemory = 0; // MB private long freeMemory = 0; // MB private long usedMemory = 0; // MB private long heapUsed; private long nonHeapUsed; private double memUsage = 0.; private double cpuUsage = 0.; private double loadAverage; // CPU 부하 private int threadCount = 0; // 현재스레드 수 private int peakThreadCount; // 어플리케이션 운영중 최대 스레드 수 private long jvmUptime; // milliseconds, - 예: uptimeMillis = 3600000 → JVM이 1시간(60분) 동안 실행 중이라는 뜻 private long loadedClassCount; // private final Map diskUsageMap = new HashMap<>(); private long diskTotal; private long diskFree; private double diskUsage; private final Map gcStatsMap = new HashMap<>(); private String gcName; private long gcCount = 0; private long gcTime = 0; private String jvmStartTime; public SystemHealth() { this.jvmStartTime = Instant.ofEpochMilli( ManagementFactory.getRuntimeMXBean().getStartTime() ).atZone(ZoneId.systemDefault()).toString(); Runtime runtime = Runtime.getRuntime(); this.maxMemory = runtime.maxMemory() / 1024 / 1024; this.cpuCores = runtime.availableProcessors(); this.osName = System.getProperty("os.name"); this.osVersion = System.getProperty("os.version"); } public void checkHealth(boolean useDisk) { Runtime runtime = Runtime.getRuntime(); this.totalMemory = runtime.totalMemory(); // Byte this.freeMemory = runtime.freeMemory(); // Byte this.usedMemory = this.totalMemory - this.freeMemory; // Byte MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); this.heapUsed = memoryMXBean.getHeapMemoryUsage().getUsed() / 1024 / 1024; this.nonHeapUsed = memoryMXBean.getNonHeapMemoryUsage().getUsed() / 1024 / 1024; this.totalMemory = this.totalMemory / 1024 / 1024; this.freeMemory = this.freeMemory / 1024 / 1024; this.usedMemory = this.usedMemory / 1024 / 1024; // System.out.println("사용 중인 메모리: " + (usedMemory / 1024 / 1024) + " MB"); // System.out.println("최대 메모리: " + (maxMemory / 1024 / 1024) + " MB"); this.memUsage = (double) this.usedMemory / this.maxMemory * 100; // For Linux/Unix, Windows(Perhaps) OperatingSystemMXBean osBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); this.cpuUsage = osBean.getSystemCpuLoad() * 100; this.loadAverage = osBean.getSystemLoadAverage(); // 1분 평균 this.threadCount = ManagementFactory.getThreadMXBean().getThreadCount(); this.peakThreadCount = ManagementFactory.getThreadMXBean().getPeakThreadCount(); this.jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime(); // long uptimeSeconds = this.jvmUptime / 1000; // long uptimeMinutes = uptimeSeconds / 60; // long uptimeHours = uptimeMinutes / 60; // long uptimeDays = uptimeHours / 24; // System.out.println("JVM Uptime: " // + uptimeDays + "d " // + (uptimeHours % 24) + "h " // + (uptimeMinutes % 60) + "m " // + (uptimeSeconds % 60) + "s"); this.loadedClassCount = ManagementFactory.getClassLoadingMXBean().getLoadedClassCount(); if (useDisk) { File root = new File("/"); if (root.exists() && root.canRead()) { this.diskTotal = root.getTotalSpace(); this.diskFree = root.getFreeSpace(); long used = this.diskTotal - this.diskFree; this.diskUsage = (double) used / this.diskTotal * 100; } } for (GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans()) { this.gcName = gc.getName(); this.gcCount += gc.getCollectionCount(); this.gcTime += gc.getCollectionTime(); gcStatsMap.put(gc.getName(), new GcStats(gc.getCollectionCount(), gc.getCollectionTime())); } // for (File root : File.listRoots()) { // if (root.exists() && root.canRead()) { // long total = root.getTotalSpace(); // long free = root.getFreeSpace(); // double usage = (double) (total - free) / total * 100; // diskUsageMap.put(root.getAbsolutePath(), usage); // } // } // GC가 전체 실행 시간의 몇 %를 차지했는지 확인 가능 // long uptime = ManagementFactory.getRuntimeMXBean().getUptime(); // ms // long gcTime = this.gcTime; // double gcRatio = (double) gcTime / uptime * 100; // log.info("GC Time: {}ms, JVM Uptime: {}ms, GC 비중: {:.2f}%", gcTime, uptime, gcRatio); } public String getFormattedUptime() { long uptimeSeconds = this.jvmUptime / 1000; long uptimeMinutes = uptimeSeconds / 60; long uptimeHours = uptimeMinutes / 60; long uptimeDays = uptimeHours / 24; return uptimeDays + "d " + (uptimeHours % 24) + "h " + (uptimeMinutes % 60) + "m " + (uptimeSeconds % 60) + "s"; } }