From ae5c50e5b44dc16339f734edc4896aaf668f9b70 Mon Sep 17 00:00:00 2001 From: qiminbao Date: Thu, 30 Oct 2025 19:31:12 +0800 Subject: [PATCH] =?UTF-8?q?1.=E7=9B=91=E6=8E=A7=E7=AD=96=E7=95=A5=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=87=E4=BB=B6=E6=A0=BC=E5=BC=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/service/impl/AgentServiceImpl.java | 52 +++++--------- .../client/service/impl/CPUServiceImpl.java | 36 ++++++++-- .../service/impl/MemoryServiceImpl.java | 16 +++-- .../client/utils/CpuUsageFromProcStat.java | 70 +++++++++++++++++++ 4 files changed, 128 insertions(+), 46 deletions(-) create mode 100644 src/main/java/com/tongran/agent/client/utils/CpuUsageFromProcStat.java diff --git a/src/main/java/com/tongran/agent/client/service/impl/AgentServiceImpl.java b/src/main/java/com/tongran/agent/client/service/impl/AgentServiceImpl.java index c30d43e..f789eca 100644 --- a/src/main/java/com/tongran/agent/client/service/impl/AgentServiceImpl.java +++ b/src/main/java/com/tongran/agent/client/service/impl/AgentServiceImpl.java @@ -299,14 +299,19 @@ public class AgentServiceImpl implements AgentService { if(upTime != 0 && GlobalConfig.MONITOR_TIME != upTime){ if(monitorJson.containsKey("contents")){ List list = new ArrayList<>(); - list.add("upTime:"+upTime); - list.add("contents:["); + list.add("{\"upTime\":"+upTime+","); + list.add("\"contents\":["); String contents = monitorJson.getString("contents"); List collectList = JSON.parseObject(contents, new TypeReference>() {}); if(CollectionUtil.isNotEmpty(collectList)){ AssertLog.info("开启或更新监控策略={}", JSON.toJSONString(collectList)); + int i = 1; for (CollectEO c : collectList) { - list.add(JSON.toJSONString(c)); + String content = JSON.toJSONString(c); + if(i != collectList.size()){ + content = JSON.toJSONString(c)+","; + } + list.add(content); String type = c.getType(); boolean collect = c.isCollect(); int interval = c.getInterval(); @@ -618,9 +623,10 @@ public class AgentServiceImpl implements AgentService { GlobalConfig.procNumInterval = 300; } } + i++; } } - list.add("]"); + list.add("]}"); String[] lines = list.stream().toArray(String[]::new); //检查外置目录是否存在 if(AdvancedAsyncDownloader.createSingleDirectoryIfNotExists(properties.getConfPath())){ @@ -1049,37 +1055,15 @@ public class AgentServiceImpl implements AgentService { if (!Files.exists(path)) { System.err.println("文件不存在: " + filePath); }else { - List lines = Files.readAllLines(path, StandardCharsets.UTF_8) - .stream() - .filter(line -> !line.trim().isEmpty()) // 去除空行(包括只有空格的行) - .collect(Collectors.toList()); + String content = Files.lines(Paths.get(filePath), StandardCharsets.UTF_8) + .filter(line -> !line.trim().isEmpty()) // 过滤掉空行 + .collect(Collectors.joining()); + AssertLog.info("监控策略配置文件信息:{}",content); + JSONObject jsonObject = JSONObject.parseObject(content); List collectList = new ArrayList<>(); - for (String data : lines) { - AssertLog.info("监控策略信息:{}",data); - if(StringUtils.isNotBlank(data)){ - if(data.startsWith("{") && data.endsWith("}")){ - JSONObject object = JSONObject.parseObject(data); - boolean collect = false; - int interval = 300; - String type = ""; - if(object.containsKey("collect")){ - collect = object.getBoolean("collect"); - } - if(object.containsKey("interval")){ - interval = object.getIntValue("collect"); - } - if(object.containsKey("type")){ - type = object.getString("type"); - } - if(StringUtils.isNotBlank(type)){ - collectList.add(CollectEO.builder() - .collect(collect) - .interval(interval) - .type(type).build()); - } - } - - } + if(jsonObject.containsKey("contents")){ + String contents = jsonObject.getString("contents"); + collectList = JSON.parseObject(contents, new TypeReference>() {}); } if(CollectionUtil.isNotEmpty(collectList)){ AssertLog.info("监控策略配置信息:{}",JSON.toJSONString(collectList)); diff --git a/src/main/java/com/tongran/agent/client/service/impl/CPUServiceImpl.java b/src/main/java/com/tongran/agent/client/service/impl/CPUServiceImpl.java index e79fc65..d173799 100644 --- a/src/main/java/com/tongran/agent/client/service/impl/CPUServiceImpl.java +++ b/src/main/java/com/tongran/agent/client/service/impl/CPUServiceImpl.java @@ -3,8 +3,9 @@ package com.tongran.agent.client.service.impl; import com.tongran.agent.client.core.vo.CpuVO; import com.tongran.agent.client.service.CPUService; import com.tongran.agent.client.utils.AgentUtil; +import com.tongran.agent.client.utils.AssertLog; +import com.tongran.agent.client.utils.CpuUsageFromProcStat; import org.springframework.stereotype.Service; - import oshi.SystemInfo; import oshi.hardware.CentralProcessor; import oshi.hardware.HardwareAbstractionLayer; @@ -41,17 +42,42 @@ public class CPUServiceImpl implements CPUService { System.out.println("5分钟平均负载: " + loadAverage[1]); System.out.println("15分钟平均负载: " + loadAverage[2]); // 3. CPU使用率(需要两次采样) - System.out.println("\n=== CPU使用率 ==="); + AssertLog.info("\n=== CPU使用率 ==="); +// System.out.println("\n=== CPU使用率 ==="); + // 预热:第一次调用可能不准 processor.getSystemCpuLoadBetweenTicks(processor.getSystemCpuLoadTicks()); TimeUnit.SECONDS.sleep(1); // 正式采样 long[] prevTicks = processor.getSystemCpuLoadTicks(); - TimeUnit.SECONDS.sleep(2); // 更长间隔,减少抖动 + TimeUnit.SECONDS.sleep(1); // 更长间隔,减少抖动 // 计算使用率 double cpuUsage = processor.getSystemCpuLoadBetweenTicks(prevTicks); - cpuVO.setUti(cpuUsage * 100); // CPU使用率 - System.out.printf("CPU 使用率: %.2f%%\n", cpuUsage * 100); + if(cpuUsage < 1.0){ + cpuVO.setUti(cpuUsage * 100); // CPU使用率 + }else { + cpuUsage = -1; + try { + // 预热 + CpuUsageFromProcStat.getCpuUsage(); + Thread.sleep(1000); + // 正式采集 + for (int i = 0; i < 5; i++) { + cpuUsage = CpuUsageFromProcStat.getCpuUsage(); + System.out.printf("CPU 使用率: %.2f%%\n", cpuUsage * 100); + Thread.sleep(2000); + } + } catch (Exception e) { + e.printStackTrace(); + } + if(cpuUsage > 0){ + cpuVO.setUti(cpuUsage * 100); // CPU使用率 + }else{ + cpuVO.setUti(cpuUsage); // CPU使用率 + } + } + AssertLog.info("CPU 使用率: {}%",cpuUsage * 100); +// System.out.printf("CPU 使用率: %.2f%%\n", cpuUsage * 100); long[] ticks = processor.getSystemCpuLoadTicks(); long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()]; diff --git a/src/main/java/com/tongran/agent/client/service/impl/MemoryServiceImpl.java b/src/main/java/com/tongran/agent/client/service/impl/MemoryServiceImpl.java index 52bb68f..53a51a0 100644 --- a/src/main/java/com/tongran/agent/client/service/impl/MemoryServiceImpl.java +++ b/src/main/java/com/tongran/agent/client/service/impl/MemoryServiceImpl.java @@ -3,6 +3,7 @@ package com.tongran.agent.client.service.impl; import com.tongran.agent.client.core.vo.MemoryVO; import com.tongran.agent.client.service.MemoryService; import com.tongran.agent.client.utils.AgentDataUtil; +import com.tongran.agent.client.utils.AssertLog; import org.springframework.stereotype.Service; import java.io.IOException; @@ -56,14 +57,15 @@ public class MemoryServiceImpl implements MemoryService { memInfo.getOrDefault("SReclaimable", 0L)); // 总内存使用率 double totalUsage = (double)(total - available) / total * 100; - System.out.printf("总内存使用率: %.2f%%\n", totalUsage); + AssertLog.info("总内存使用率: {}%",totalUsage); +// System.out.printf("总内存使用率: %.2f%%\n", totalUsage); // 实际内存使用率 - long cached = memInfo.getOrDefault("Cached", 0L) + - memInfo.getOrDefault("SReclaimable", 0L); - long buffers = memInfo.getOrDefault("Buffers", 0L); - double actualUsage = (double)(total - available - cached - buffers) / total * 100; - System.out.printf("实际内存使用率: %.2f%%\n", actualUsage); - memoryVO.setUntilzation(actualUsage); //内存利用率 +// long cached = memInfo.getOrDefault("Cached", 0L) + +// memInfo.getOrDefault("SReclaimable", 0L); +// long buffers = memInfo.getOrDefault("Buffers", 0L); +// double actualUsage = (double)(total - available - cached - buffers) / total * 100; +// System.out.printf("实际内存使用率: %.2f%%\n", actualUsage); + memoryVO.setUntilzation(totalUsage); //内存利用率 } catch (IOException e) { e.printStackTrace(); } diff --git a/src/main/java/com/tongran/agent/client/utils/CpuUsageFromProcStat.java b/src/main/java/com/tongran/agent/client/utils/CpuUsageFromProcStat.java new file mode 100644 index 0000000..fb73efa --- /dev/null +++ b/src/main/java/com/tongran/agent/client/utils/CpuUsageFromProcStat.java @@ -0,0 +1,70 @@ +package com.tongran.agent.client.utils; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; + +public class CpuUsageFromProcStat { + + private static final String PROC_STAT = "/proc/stat"; + private static long[] prevCpuTime = null; + + public static double getCpuUsage() throws Exception { + List lines = Files.readAllLines(Paths.get(PROC_STAT)); + for (String line : lines) { + if (line.startsWith("cpu ")) { + long[] current = parseCpuLine(line); + if (prevCpuTime == null) { + prevCpuTime = current; + Thread.sleep(500); // 初始等待 + return 0.0; // 第一次不返回数据 + } + + double usage = calculateCpuUsage(prevCpuTime, current); + prevCpuTime = current; // 更新 + return usage; + } + } + throw new RuntimeException("无法读取 /proc/stat 中的 cpu 数据"); + } + + private static long[] parseCpuLine(String line) { + String[] parts = line.split("\\s+"); + // index: user, nice, system, idle, iowait, irq, softirq, steal + long user = Long.parseLong(parts[1]); + long nice = Long.parseLong(parts[2]); + long system = Long.parseLong(parts[3]); + long idle = Long.parseLong(parts[4]); + long iowait = Long.parseLong(parts[5]); + long irq = Long.parseLong(parts[6]); + long softirq = Long.parseLong(parts[7]); + + long idleTotal = idle + iowait; + long systemTotal = user + nice + system + irq + softirq; + long total = idleTotal + systemTotal; + + return new long[]{idleTotal, total}; + } + + private static double calculateCpuUsage(long[] prev, long[] curr) { + long idleDiff = curr[0] - prev[0]; + long totalDiff = curr[1] - prev[1]; + + if (totalDiff <= 0) return 0.0; + + return 1.0 - ((double) idleDiff / totalDiff); + } + + public static void main(String[] args) throws Exception { + // 预热 + getCpuUsage(); + Thread.sleep(1000); + + // 正式采集 + for (int i = 0; i < 5; i++) { + double usage = getCpuUsage(); + System.out.printf("CPU 使用率: %.2f%%\n", usage * 100); + Thread.sleep(2000); + } + } +} \ No newline at end of file