From 4ed1a664666044335d76d499d2ea04af59f920cc Mon Sep 17 00:00:00 2001 From: gaoyutao Date: Fri, 16 Jan 2026 18:11:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0cpu=E6=B8=A9=E5=BA=A6?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/utils/EchartsDataUtils.java | 201 ++++++++++++------ .../tongran/common/core/utils/SpeedUtils.java | 18 +- .../system/domain/EpsNodeBandwidth.java | 4 +- .../mapper/system/EpsNodeBandwidthMapper.xml | 2 +- .../controller/InitialCpuInfoController.java | 8 + .../tongran/rocketmq/domain/AllDiskName.java | 3 + .../rocketmq/domain/InitialCpuInfo.java | 2 + .../rocketmq/handler/MessageHandler.java | 3 + .../service/IInitialCpuInfoService.java | 7 + .../service/impl/AllDiskNameServiceImpl.java | 4 + .../impl/InitialCpuInfoServiceImpl.java | 15 ++ .../impl/InitialDiskInfoServiceImpl.java | 2 +- .../mapper/rocketmq/AllDiskNameMapper.xml | 22 +- .../mapper/rocketmq/InitialCpuInfoMapper.xml | 51 ++++- 14 files changed, 242 insertions(+), 100 deletions(-) diff --git a/tongran-common/tongran-common-core/src/main/java/com/tongran/common/core/utils/EchartsDataUtils.java b/tongran-common/tongran-common-core/src/main/java/com/tongran/common/core/utils/EchartsDataUtils.java index 14f1e45..02eca38 100644 --- a/tongran-common/tongran-common-core/src/main/java/com/tongran/common/core/utils/EchartsDataUtils.java +++ b/tongran-common/tongran-common-core/src/main/java/com/tongran/common/core/utils/EchartsDataUtils.java @@ -53,7 +53,7 @@ public class EchartsDataUtils { return Math.round(microseconds / 1_000_000.0 * 100.0) / 100.0; } /** - * 构建ECharts图表数据(带时间补全和特殊值处理)- 修复版本 + * 构建ECharts图表数据(带时间补全和特殊值处理)- 最终修复版本 */ public static Map buildEchartsDataAutoPadding( List list, @@ -84,9 +84,6 @@ public class EchartsDataUtils { .sorted(Comparator.comparing(timeExtractor)) .collect(Collectors.toList()); - // 自动检测时间间隔 - long timeInterval = detectTimeInterval(sortedList, timeExtractor); - // 获取数据实际的时间范围 Date actualStartTime = timeExtractor.apply(sortedList.get(0)); Date actualEndTime = timeExtractor.apply(sortedList.get(sortedList.size() - 1)); @@ -96,39 +93,13 @@ public class EchartsDataUtils { long sparseInterval = totalTimeRange > 12L * 30 * 24 * 60 * 60 * 1000 ? 30L * 24 * 60 * 60 * 1000 : 2L * 24 * 60 * 60 * 1000; - // 生成完整的时间序列 - List fullTimeSeries = new ArrayList<>(); - - // 1. 开始时间到数据开始时间(稀疏间隔) - if (startDate.before(actualStartTime)) { - List beforeSeries = generateSparseTimeSeries(startDate, actualStartTime, sparseInterval); - fullTimeSeries.addAll(beforeSeries); - } - - // 2. 数据开始时间到数据结束时间 - 以第一个数据点的时间为基准生成序列 - List dataSeries = generateTimeSeriesFromDataPoints(actualStartTime, actualEndTime, - timeInterval, actualStartTime); - fullTimeSeries.addAll(dataSeries); - - // 3. 数据结束时间到结束时间(稀疏间隔) - if (actualEndTime.before(endDate)) { - // 从actualEndTime的下一个时间点开始 - Calendar cal = Calendar.getInstance(); - cal.setTime(actualEndTime); - cal.add(Calendar.MILLISECOND, (int)timeInterval); - Date nextAfterActualEnd = cal.getTime(); - - if (nextAfterActualEnd.before(endDate) || nextAfterActualEnd.equals(endDate)) { - List afterSeries = generateSparseTimeSeries(nextAfterActualEnd, endDate, sparseInterval); - fullTimeSeries.addAll(afterSeries); - } - } - - // 去重并排序 - fullTimeSeries = fullTimeSeries.stream() - .distinct() - .sorted() - .collect(Collectors.toList()); + // 核心修改:生成X轴时间序列 + List xAxisTimes = generateXAxisTimeSeries( + startDate, endDate, + actualStartTime, actualEndTime, + sortedList, timeExtractor, + sparseInterval + ); // 创建时间到数据的映射 Map timeDataMap = new HashMap<>(); @@ -152,7 +123,7 @@ public class EchartsDataUtils { dataExtractors.keySet().forEach(name -> yData.put(name, new ArrayList<>())); - for (Date time : fullTimeSeries) { + for (Date time : xAxisTimes) { // X轴数据 String timeStr = parseDateToStr(time); xAxisData.add(timeStr); @@ -177,7 +148,7 @@ public class EchartsDataUtils { } else { // 智能数据补全 if (isInDataRange) { - // 在数据时间范围内但该时间点无数据(数据缺失点) + // 在数据时间范围内但该时间点无数据 seriesData.add(getDefaultValue(name, fixedPercentile95Value, xAxisData.size()-1, hasRealData)); } else { // 在数据时间范围外 @@ -200,37 +171,54 @@ public class EchartsDataUtils { } /** - * 从第一个数据点开始生成时间序列 + * 生成X轴时间序列(核心方法) + * 策略:优先使用实际数据的时间点,然后在数据点之间按需补全 */ - private static List generateTimeSeriesFromDataPoints(Date start, Date end, - long interval, Date firstDataPoint) { + private static List generateXAxisTimeSeries( + Date queryStart, Date queryEnd, + Date dataStart, Date dataEnd, + List sortedList, Function timeExtractor, + long sparseInterval) { + List timeSeries = new ArrayList<>(); - if (interval <= 0) { - interval = 300000L; // 默认5分钟 + // 1. 查询开始时间到数据开始时间(稀疏间隔) + if (queryStart.before(dataStart)) { + List beforeSeries = generateTimeSeries(queryStart, dataStart, sparseInterval, false); + timeSeries.addAll(beforeSeries); } - // 使用第一个数据点的时间作为基准 - Calendar calendar = Calendar.getInstance(); - calendar.setTime(firstDataPoint); - calendar.set(Calendar.MILLISECOND, 0); + // 2. 数据时间范围内的处理 + if (sortedList != null && !sortedList.isEmpty()) { + // 优先使用实际数据的所有时间点 + List dataTimePoints = sortedList.stream() + .map(timeExtractor) + .sorted() + .collect(Collectors.toList()); + timeSeries.addAll(dataTimePoints); - // 从第一个数据点开始向前找,直到找到小于等于start的时间点 - while (calendar.getTime().after(start)) { - calendar.add(Calendar.MILLISECOND, -(int)interval); + // 检测数据点之间的间隔,补全缺失的时间点 + if (dataTimePoints.size() > 1) { + List filledSeries = fillMissingTimePoints(dataTimePoints); + timeSeries.addAll(filledSeries); + } } - // 如果当前位置在start之前,前进一个间隔 - if (calendar.getTime().before(start)) { - calendar.add(Calendar.MILLISECOND, (int)interval); - } + // 3. 数据结束时间到查询结束时间(稀疏间隔) + if (dataEnd.before(queryEnd)) { + // 从数据结束时间的下一个稀疏间隔点开始 + Calendar cal = Calendar.getInstance(); + cal.setTime(dataEnd); + cal.add(Calendar.MILLISECOND, (int)sparseInterval); + Date nextAfterDataEnd = cal.getTime(); - // 生成时间序列 - while (!calendar.getTime().after(end)) { - timeSeries.add(calendar.getTime()); - calendar.add(Calendar.MILLISECOND, (int)interval); + if (nextAfterDataEnd.before(queryEnd) || nextAfterDataEnd.equals(queryEnd)) { + List afterSeries = generateTimeSeries(nextAfterDataEnd, queryEnd, sparseInterval, false); + timeSeries.addAll(afterSeries); + } } + // 去重、排序 return timeSeries.stream() .distinct() .sorted() @@ -238,21 +226,103 @@ public class EchartsDataUtils { } /** - * 生成稀疏时间序列 + * 补全缺失的时间点 + * 在相邻数据点之间,如果间隔太大,插入中间点 */ - private static List generateSparseTimeSeries(Date start, Date end, long interval) { + private static List fillMissingTimePoints(List dataTimePoints) { + List filledPoints = new ArrayList<>(); + + if (dataTimePoints.size() < 2) { + return filledPoints; + } + + // 检测常见间隔 + long commonInterval = detectCommonInterval(dataTimePoints); + + for (int i = 0; i < dataTimePoints.size() - 1; i++) { + Date current = dataTimePoints.get(i); + Date next = dataTimePoints.get(i + 1); + long diff = next.getTime() - current.getTime(); + + // 如果间隔大于常见间隔的1.5倍,说明中间有缺失 + if (diff > commonInterval * 1.5) { + // 计算可以插入几个点 + int pointsToInsert = (int) (diff / commonInterval) - 1; + + Calendar cal = Calendar.getInstance(); + cal.setTime(current); + + for (int j = 1; j <= pointsToInsert; j++) { + cal.add(Calendar.MILLISECOND, (int)commonInterval); + Date insertedPoint = cal.getTime(); + + // 确保插入的点不晚于next + if (insertedPoint.before(next)) { + filledPoints.add(insertedPoint); + } + } + } + } + + return filledPoints; + } + + /** + * 检测常见时间间隔 + */ + private static long detectCommonInterval(List timePoints) { + if (timePoints.size() < 2) { + return 300000L; // 默认5分钟 + } + + Map intervalCount = new HashMap<>(); + for (int i = 1; i < timePoints.size(); i++) { + long interval = timePoints.get(i).getTime() - timePoints.get(i-1).getTime(); + if (interval > 0) { + intervalCount.merge(interval, 1, Integer::sum); + } + } + + if (intervalCount.isEmpty()) { + return 300000L; + } + + return intervalCount.entrySet().stream() + .max(Map.Entry.comparingByValue()) + .map(Map.Entry::getKey) + .orElse(300000L); + } + + /** + * 生成时间序列 + * @param alignToInterval 是否对齐到时间间隔 + */ + private static List generateTimeSeries(Date start, Date end, long interval, boolean alignToInterval) { List timeSeries = new ArrayList<>(); if (interval <= 0) { - interval = 2L * 24 * 60 * 60 * 1000; // 默认2天 + interval = 300000L; } Calendar calendar = Calendar.getInstance(); calendar.setTime(start); calendar.set(Calendar.MILLISECOND, 0); + if (alignToInterval) { + // 对齐到间隔 + long startMillis = calendar.getTimeInMillis(); + long normalizedStart = (startMillis / interval) * interval; + calendar.setTimeInMillis(normalizedStart); + + if (normalizedStart < startMillis) { + calendar.add(Calendar.MILLISECOND, (int)interval); + } + } + // 包含开始时间 - timeSeries.add(calendar.getTime()); + if (!calendar.getTime().after(end)) { + timeSeries.add(calendar.getTime()); + } while (true) { calendar.add(Calendar.MILLISECOND, (int)interval); @@ -262,10 +332,7 @@ public class EchartsDataUtils { timeSeries.add(calendar.getTime()); } - return timeSeries.stream() - .distinct() - .sorted() - .collect(Collectors.toList()); + return timeSeries; } /** diff --git a/tongran-common/tongran-common-core/src/main/java/com/tongran/common/core/utils/SpeedUtils.java b/tongran-common/tongran-common-core/src/main/java/com/tongran/common/core/utils/SpeedUtils.java index 42a61dc..602ae65 100644 --- a/tongran-common/tongran-common-core/src/main/java/com/tongran/common/core/utils/SpeedUtils.java +++ b/tongran-common/tongran-common-core/src/main/java/com/tongran/common/core/utils/SpeedUtils.java @@ -385,35 +385,27 @@ public class SpeedUtils { } public static String determineUnitByValue(Long value) { if (value == null || value == 0) { - return "KB"; + return "Kb"; } // 注意:这里使用二进制单位(1024) - if (value >= 1024L * 1024 * 1024 * 1024) { // >= 1TB - return "TB"; - } else if (value >= 1024L * 1024 * 1024) { // >= 1GB - return "GB"; + if (value >= 1024L * 1024 * 1024) { // >= 1GB + return "Gb"; } else if (value >= 1024L * 1024) { // >= 1MB - return "MB"; + return "Mb"; } else { - return "KB"; + return "Kb"; } } // 工具方法:获取单位换算除数 public static BigDecimal get1024Divisor(String unit) { switch (unit) { - case "GB": case "Gb": return new BigDecimal(1024L * 1024 * 1024); // 1GB = 1024^3 - case "MB": case "Mb": return new BigDecimal(1024L * 1024); // 1MB = 1024^2 - case "KB": case "Kb": return new BigDecimal(1024); // 1KB = 1024 - case "TB": - case "Tb": - return new BigDecimal(1024L * 1024 * 1024 * 1024); // 1TB = 1024^4 default: return new BigDecimal(1024); // 默认返回KB的除数 } diff --git a/tongran-modules/tongran-system/src/main/java/com/tongran/system/domain/EpsNodeBandwidth.java b/tongran-modules/tongran-system/src/main/java/com/tongran/system/domain/EpsNodeBandwidth.java index 4bafa63..707009a 100644 --- a/tongran-modules/tongran-system/src/main/java/com/tongran/system/domain/EpsNodeBandwidth.java +++ b/tongran-modules/tongran-system/src/main/java/com/tongran/system/domain/EpsNodeBandwidth.java @@ -88,11 +88,11 @@ public class EpsNodeBandwidth extends BaseEntity private String interfaceName; /** 资源类型(1服务器,2交换机) */ - @Excel(name = "资源类型") + @Excel(name = "资源类型", readConverterExp = "1=服务器,2=交换机") private String resourceType; /** 接口连接设备类型(1服务器,2机房出口) */ - @Excel(name = "接口连接设备类型") + @Excel(name = "接口连接设备类型", readConverterExp = "1=服务器,2=机房出口,3=交换机上联,4=交换机下联") private String interfaceLinkDeviceType; /** 业务名称 */ @Excel(name = "业务名称") diff --git a/tongran-modules/tongran-system/src/main/resources/mapper/system/EpsNodeBandwidthMapper.xml b/tongran-modules/tongran-system/src/main/resources/mapper/system/EpsNodeBandwidthMapper.xml index a46d1df..3ad322d 100644 --- a/tongran-modules/tongran-system/src/main/resources/mapper/system/EpsNodeBandwidthMapper.xml +++ b/tongran-modules/tongran-system/src/main/resources/mapper/system/EpsNodeBandwidthMapper.xml @@ -55,7 +55,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and machine_flow = #{machineFlow} and uplink_switch like concat('%', #{uplinkSwitch}, '%') and switch_sn = #{switchSn} - and interface_name like concat('%', #{interfaceName}, '%') + and interface_name = #{interfaceName} and resource_type = #{resourceType} and interface_link_device_type = #{interfaceLinkDeviceType} and effective_bandwidth_95_daily = #{effectiveBandwidth95Daily} diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/controller/InitialCpuInfoController.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/controller/InitialCpuInfoController.java index 64611de..b09b881 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/controller/InitialCpuInfoController.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/controller/InitialCpuInfoController.java @@ -112,4 +112,12 @@ public class InitialCpuInfoController extends BaseController Map echartsData = initialCpuInfoService.cpuTimeEcharts(initialCpuInfo); return success(echartsData); } + /** + * 查询CPU温度信息并封装为多折线ECharts图表数据 + */ + @PostMapping("/cupTemperatureEcharts") + public AjaxResult cupTemperatureEcharts(@RequestBody InitialCpuInfo initialCpuInfo) { + Map echartsData = initialCpuInfoService.cupTemperatureEcharts(initialCpuInfo); + return success(echartsData); + } } diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/AllDiskName.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/AllDiskName.java index 6dbe829..b54052e 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/AllDiskName.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/AllDiskName.java @@ -29,6 +29,9 @@ public class AllDiskName extends BaseEntity /** 磁盘状态(0:丢失,1:存在) */ @Excel(name = "磁盘状态(0:丢失,1:存在)") private Integer status; + /** 执行卸载(0未执行,1已执行) */ + @Excel(name = "执行卸载(0未执行,1已执行)") + private Integer umountFlag; /** 读取IOPS */ @Excel(name = "读取IOPS") diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/InitialCpuInfo.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/InitialCpuInfo.java index 6b4cb7b..67ba2f3 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/InitialCpuInfo.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/InitialCpuInfo.java @@ -72,6 +72,8 @@ public class InitialCpuInfo extends BaseEntity /** CPU用户进程所花费的时间(秒) */ @Excel(name = "CPU用户进程所花费的时间") private Long user; + /** cpu温度 */ + private Long temperature; /** 开始时间 */ private String startTime; /** 结束时间 */ diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/handler/MessageHandler.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/handler/MessageHandler.java index c9ae3da..c98fff3 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/handler/MessageHandler.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/handler/MessageHandler.java @@ -549,6 +549,9 @@ public class MessageHandler { cpus.forEach(iface -> { iface.setClientId(message.getClientId()); iface.setCreateTime(createTime); + if(iface.getTemperature() == 0L){ + iface.setTemperature(null); + } }); // 初始CPU数据入库 initialCpuInfoService.batchInsertInitialCpuInfo(cpus); diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/IInitialCpuInfoService.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/IInitialCpuInfoService.java index d53f3af..0d4ae9f 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/IInitialCpuInfoService.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/IInitialCpuInfoService.java @@ -71,4 +71,11 @@ public interface IInitialCpuInfoService Map cupLoadEcharts(InitialCpuInfo initialCpuInfo); Map cpuTimeEcharts(InitialCpuInfo initialCpuInfo); + + /** + * cpu温度 + * @param initialCpuInfo + * @return + */ + Map cupTemperatureEcharts(InitialCpuInfo initialCpuInfo); } diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/AllDiskNameServiceImpl.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/AllDiskNameServiceImpl.java index 5aabbea..d9a0309 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/AllDiskNameServiceImpl.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/AllDiskNameServiceImpl.java @@ -137,6 +137,10 @@ public class AllDiskNameServiceImpl implements IAllDiskNameService if(processType == 1){ policyTypeVo.setDiskIopsTest(allDiskName.getName()); }else if(processType ==2){ + AllDiskName updateDisk = new AllDiskName(); + updateDisk.setId(id); + updateDisk.setUmountFlag(1); + allDiskNameMapper.updateAllDiskName(updateDisk); policyTypeVo.setUmountDisk(allDiskName.getName()); } MessageProducer messageProducer = new MessageProducer(); diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialCpuInfoServiceImpl.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialCpuInfoServiceImpl.java index bd2c99e..36eedc2 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialCpuInfoServiceImpl.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialCpuInfoServiceImpl.java @@ -160,5 +160,20 @@ public class InitialCpuInfoServiceImpl implements IInitialCpuInfoService return EchartsDataUtils.buildEchartsData(list,InitialCpuInfo::getCreateTime, extractors); } + /** + * cpu负载 + * @param initialCpuInfo + * @return + */ + @Override + public Map cupTemperatureEcharts(InitialCpuInfo initialCpuInfo) { + // 查询原始CPU监控数据并按时间排序 + List list = initialCpuInfoMapper.selectInitialCpuInfoList(initialCpuInfo); + + Map> extractors = new LinkedHashMap<>(); + extractors.put("temperatureData", InitialCpuInfo::getTemperature); + + return EchartsDataUtils.buildEchartsDataAutoPadding(list, InitialCpuInfo::getCreateTime, extractors, initialCpuInfo.getStartTime(), initialCpuInfo.getEndTime()); + } } diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialDiskInfoServiceImpl.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialDiskInfoServiceImpl.java index b1d430c..4006911 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialDiskInfoServiceImpl.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialDiskInfoServiceImpl.java @@ -253,7 +253,7 @@ public class InitialDiskInfoServiceImpl implements IInitialDiskInfoService public Map usedSpaceEcharts(InitialDiskInfo initialDiskInfo) { initialDiskInfo.setType("HDD"); List list = getDistInfoSharding(initialDiskInfo); - String unit = "KB"; + String unit = "Kb"; if(list != null && !list.isEmpty()){ Long totalUsedSpace = 0L; for (InitialDiskInfo diskInfo : list) { diff --git a/tongran-rocketmq/src/main/resources/mapper/rocketmq/AllDiskNameMapper.xml b/tongran-rocketmq/src/main/resources/mapper/rocketmq/AllDiskNameMapper.xml index 83599bf..d0f53b1 100644 --- a/tongran-rocketmq/src/main/resources/mapper/rocketmq/AllDiskNameMapper.xml +++ b/tongran-rocketmq/src/main/resources/mapper/rocketmq/AllDiskNameMapper.xml @@ -1,9 +1,9 @@ + PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - + @@ -11,6 +11,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + @@ -18,7 +19,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - select id, client_id, name, status, read_iops, write_iops, create_time, update_time, create_by, update_by from all_disk_name + select id, client_id, name, status, read_iops, write_iops, umount_flag, create_time, update_time, create_by, update_by from all_disk_name - + - + and client_id = #{clientId} + and temperature = #{temperature} and create_time >= #{startTime} and create_time <= #{endTime} order by create_time desc - + where client_id = #{clientId}