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 44d2404..ab76d13 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 @@ -90,8 +90,15 @@ public class EchartsDataUtils { // 计算稀疏间隔 long totalTimeRange = endDate.getTime() - startDate.getTime(); - long sparseInterval = totalTimeRange > 12L * 30 * 24 * 60 * 60 * 1000 ? - 30L * 24 * 60 * 60 * 1000 : 2L * 24 * 60 * 60 * 1000; + + long sparseInterval; + if (totalTimeRange > 12L * 30 * 24 * 60 * 60 * 1000) { // 大于12个月 + sparseInterval = 30L * 24 * 60 * 60 * 1000; // 30天间隔 + } else if (totalTimeRange <= 24L * 60 * 60 * 1000) { // 小于等于24小时 + sparseInterval = 5L * 60 * 1000; // 5分钟间隔 + } else { // 其他情况(大于24小时,小于等于12个月) + sparseInterval = 2L * 24 * 60 * 60 * 1000; // 2天间隔 + } // 核心修改:生成X轴时间序列 List xAxisTimes = generateXAxisTimeSeries( @@ -323,6 +330,16 @@ public class EchartsDataUtils { if (normalizedStart < startMillis) { calendar.add(Calendar.MILLISECOND, (int)interval); } + } else { + // 对齐到下一分钟的0秒 + // 先将秒和毫秒清零 + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + + // 如果当前时间不是整分钟,就跳到下一分钟 + if (calendar.getTime().before(start)) { + calendar.add(Calendar.MINUTE, 1); + } } // 包含开始时间 diff --git a/tongran-common/tongran-common-core/src/main/java/com/tongran/common/core/utils/EchartsMoreDataUtils.java b/tongran-common/tongran-common-core/src/main/java/com/tongran/common/core/utils/EchartsMoreDataUtils.java index 1c13452..fae927d 100644 --- a/tongran-common/tongran-common-core/src/main/java/com/tongran/common/core/utils/EchartsMoreDataUtils.java +++ b/tongran-common/tongran-common-core/src/main/java/com/tongran/common/core/utils/EchartsMoreDataUtils.java @@ -182,9 +182,15 @@ public class EchartsMoreDataUtils { // 计算稀疏间隔 long totalTimeRange = endDate.getTime() - startDate.getTime(); - long sparseInterval = totalTimeRange > 12L * 30 * 24 * 60 * 60 * 1000 ? - 30L * 24 * 60 * 60 * 1000 : 2L * 24 * 60 * 60 * 1000; + long sparseInterval; + if (totalTimeRange > 12L * 30 * 24 * 60 * 60 * 1000) { // 大于12个月 + sparseInterval = 30L * 24 * 60 * 60 * 1000; // 30天间隔 + } else if (totalTimeRange <= 24L * 60 * 60 * 1000) { // 小于等于24小时 + sparseInterval = 5L * 60 * 1000; // 5分钟间隔 + } else { // 其他情况(大于24小时,小于等于12个月) + sparseInterval = 2L * 24 * 60 * 60 * 1000; // 2天间隔 + } // 使用默认的5分钟作为数据期间间隔 long dataInterval = 300000L; @@ -421,7 +427,7 @@ public class EchartsMoreDataUtils { */ private static long normalizeTime(Date time, long interval) { long timeMillis = time.getTime(); - return (timeMillis / interval) * interval; + return ((timeMillis + interval - 1) / interval) * interval; } public static Map sortInterfaceMap(Map interfaceMap, String mainName, boolean hasSub) { List> list = new ArrayList<>(interfaceMap.entrySet()); diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/InitialSystemOtherCollectData.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/InitialSystemOtherCollectData.java index ab256ba..5fb53ba 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/InitialSystemOtherCollectData.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/InitialSystemOtherCollectData.java @@ -35,4 +35,6 @@ public class InitialSystemOtherCollectData extends BaseEntity private String endTime; /** 表名 */ private String tableName; + /** 已用内存 */ + private String memUsed; } 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 5fc5a7c..1f4b11b 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 @@ -45,6 +45,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; @@ -192,12 +193,14 @@ public class MessageHandler { localIsp = networkInfoChild.getIsp(); } } + // 在计算百分比之前,先并行查询所有IP归属地 + Map> ipLocationCache = new ConcurrentHashMap<>(); + tcpdumpVoList.parallelStream().forEach(vo -> { + ipLocationCache.computeIfAbsent(vo.getIp(), ip -> queryIpLocation(ip)); + }); // 计算总数量 Double totalCount = 0.0; - for (TcpdumpVo tcpdumpVo : tcpdumpVoList) { - totalCount += tcpdumpVo.getCount(); - } // 分别统计IPv4和IPv6 Map> ipTypeMap = new HashMap<>(); @@ -206,6 +209,7 @@ public class MessageHandler { // 按类型分类 for (TcpdumpVo tcpdumpVo : tcpdumpVoList) { + totalCount += tcpdumpVo.getCount(); String ip = tcpdumpVo.getIp(); String type = checkIPVersion(ip); if ("IPv4".equals(type)) { @@ -232,7 +236,7 @@ public class MessageHandler { // 按省份运营商分组统计(过滤本地省份) Map v4StatMap = new HashMap<>(); for (TcpdumpVo tcpdumpVo : ipTypeMap.get("IPv4")) { - Map locationInfo = queryIpLocation(tcpdumpVo.getIp()); + Map locationInfo = ipLocationCache.get(tcpdumpVo.getIp()); if (locationInfo != null) { String operator = locationInfo.get("operator"); String province = locationInfo.get("province"); @@ -277,7 +281,7 @@ public class MessageHandler { // 按省份运营商分组统计(过滤本地省份) Map v6StatMap = new HashMap<>(); for (TcpdumpVo tcpdumpVo : ipTypeMap.get("IPv6")) { - Map locationInfo = queryIpLocation(tcpdumpVo.getIp()); + Map locationInfo = ipLocationCache.get(tcpdumpVo.getIp()); if (locationInfo != null) { String operator = locationInfo.get("operator"); String province = locationInfo.get("province"); diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/mapper/InitialSystemOtherCollectDataMapper.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/mapper/InitialSystemOtherCollectDataMapper.java index c494808..a2c5eea 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/mapper/InitialSystemOtherCollectDataMapper.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/mapper/InitialSystemOtherCollectDataMapper.java @@ -80,4 +80,6 @@ public interface InitialSystemOtherCollectDataMapper * @return */ String getMemTotalSize(InitialSystemOtherCollectData otherCollectData); + + String getMemTotalSizeNoConvert(InitialSystemOtherCollectData otherCollectData); } diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialBandwidthTrafficServiceImpl.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialBandwidthTrafficServiceImpl.java index 0b5865d..a447841 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialBandwidthTrafficServiceImpl.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialBandwidthTrafficServiceImpl.java @@ -704,94 +704,72 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf return resultMap; } +// @Override +// public Map pingDroppedEcharts(InitialBandwidthTraffic initialBandwidthTraffic) { +// // 流量信息 +// List list = getListByTableName(initialBandwidthTraffic); +// Map> extractors = new LinkedHashMap<>(); +// extractors.put("pingDropped", info -> info.getPingDropped()); +// +// return EchartsDataUtils.buildEchartsDataAutoPadding( +// list, InitialBandwidthTraffic::getCreateTime, extractors, +// initialBandwidthTraffic.getStartTime(), initialBandwidthTraffic.getEndTime() +// ); +// } @Override public Map pingDroppedEcharts(InitialBandwidthTraffic initialBandwidthTraffic) { - // 流量信息 + // 主网卡流量信息 List list = getListByTableName(initialBandwidthTraffic); + String originalName = initialBandwidthTraffic.getName(); + String name = originalName; + if (originalName != null && originalName.contains("(")) { + int index = originalName.indexOf("("); + name = originalName.substring(0, index); + } + // 如果是Ethernet类型,查询子网卡 + if(isEthernetInterface(name)){ + RmNetworkInterfaceChild query = new RmNetworkInterfaceChild(); + query.setClientId(initialBandwidthTraffic.getClientId()); + query.setParentInterface(name); + List children = rmNetworkInterfaceChildMapper.selectRmNetworkInterfaceChildList(query); + if(children != null && !children.isEmpty()){ + // 按时间分组的主网卡数据 + Map timeGroupMap = new HashMap<>(); + for (InitialBandwidthTraffic item : list) { + if (item.getCreateTime() != null) { + timeGroupMap.put(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", item.getCreateTime()), item); + } + } + for (RmNetworkInterfaceChild child : children) { + InitialBandwidthTraffic childTraffic = new InitialBandwidthTraffic(); + BeanUtils.copyProperties(initialBandwidthTraffic, childTraffic); + childTraffic.setName(child.getInterfaceName()); + List childTrafficList = getListByTableName(childTraffic); + if(childTrafficList != null && !childTrafficList.isEmpty()){ + // 将子网卡数据累加到对应时间点的主网卡数据中 + for (InitialBandwidthTraffic childItem : childTrafficList) { + if (childItem.getCreateTime() != null && childItem.getPingDropped() != null) { + InitialBandwidthTraffic mainItem = timeGroupMap.get(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", childItem.getCreateTime())); + if (mainItem != null) { + // 累加pingDropped值 + Double mainValue = mainItem.getPingDropped() != null ? mainItem.getPingDropped() : 0; + Double childValue = childItem.getPingDropped() != null ? childItem.getPingDropped() : 0; + // 修改原list中pingDropped的值 + mainItem.setPingDropped(mainValue + childValue); + } + } + } + } + } + } + } Map> extractors = new LinkedHashMap<>(); extractors.put("pingDropped", info -> info.getPingDropped()); - return EchartsDataUtils.buildEchartsDataAutoPadding( list, InitialBandwidthTraffic::getCreateTime, extractors, initialBandwidthTraffic.getStartTime(), initialBandwidthTraffic.getEndTime() ); } -// @Override -// public Map pingDroppedEcharts(InitialBandwidthTraffic initialBandwidthTraffic) { -// // 主网卡流量信息 -// List mainList = getListByTableName(initialBandwidthTraffic); -// String originalName = initialBandwidthTraffic.getName(); -// String name = originalName; -// -// if (originalName != null && originalName.contains("(")) { -// int index = originalName.indexOf("("); -// name = originalName.substring(0, index); -// } -// -// // 存储所有网卡的数据 -// Map> interfaceDataMap = new LinkedHashMap<>(); -// // 展示关系 -// Map showRealation = new HashMap<>(); -// -// // 添加主网卡数据 -// interfaceDataMap.put(name, mainList); -// showRealation.put(name+"pingDropped", name+"的ping丢包率"); -// -// boolean hasSubInterface = false; -// -// // 如果是Ethernet类型,查询子网卡 -// if(isEthernetInterface(name)){ -// RmNetworkInterfaceChild query = new RmNetworkInterfaceChild(); -// query.setClientId(initialBandwidthTraffic.getClientId()); -// query.setParentInterface(name); -// List children = rmNetworkInterfaceChildMapper.selectRmNetworkInterfaceChildList(query); -// if(children != null && !children.isEmpty()){ -// hasSubInterface = true; -// for (RmNetworkInterfaceChild child : children) { -// InitialBandwidthTraffic childTraffic = new InitialBandwidthTraffic(); -// BeanUtils.copyProperties(initialBandwidthTraffic, childTraffic); -// childTraffic.setName(child.getInterfaceName()); -// List childTrafficList = getListByTableName(childTraffic); -// -// if(childTrafficList != null && !childTrafficList.isEmpty()){ -// interfaceDataMap.put(child.getInterfaceName(), childTrafficList); -// showRealation.put(child.getInterfaceName()+"pingDropped", child.getInterfaceName() + "的ping丢包率"); -// } -// } -// } -// } -// -// try { -// // 获取ping丢包率图表数据 -// Map resultMap = EchartsMoreDataUtils.buildMultiInterfaceEchartsDataWithTotal( -// interfaceDataMap, -// InitialBandwidthTraffic::getCreateTime, -// info -> info.getPingDropped() != null ? new BigDecimal(info.getPingDropped()) : null, -// null, // 出站流量设为null,因为ping丢包率只有单向数据 -// initialBandwidthTraffic.getStartTime(), -// initialBandwidthTraffic.getEndTime(), -// BigDecimal.ONE // 使用1作为除数,因为ping丢包率通常是百分比,不需要单位转换 -// ); -// -// // 如果有子网卡,添加总丢包率显示 -// if(hasSubInterface){ -// showRealation.put("totalPingDropped", name+"总ping丢包率"); -// } -// -// // 排序显示关系 -// Map sortedShowRealation = EchartsMoreDataUtils.sortInterfaceMap(showRealation, name, hasSubInterface); -// resultMap.put("showRealation", sortedShowRealation); -// -// // 添加单位信息(ping丢包率通常用百分比表示) -// resultMap.put("unit", "%"); -// -// return resultMap; -// -// } catch (Exception e){ -// e.printStackTrace(); -// return new HashMap<>(); -// } -// } @Override public int countByClientIdAndTime(InitialBandwidthTraffic countQuery) { diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialSystemOtherCollectDataServiceImpl.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialSystemOtherCollectDataServiceImpl.java index 77f8c1b..0ee6eb1 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialSystemOtherCollectDataServiceImpl.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/InitialSystemOtherCollectDataServiceImpl.java @@ -175,7 +175,6 @@ public class InitialSystemOtherCollectDataServiceImpl implements IInitialSystemO }) .collect(Collectors.toList()); } - /** * 查询系统登陆用户数(个)监控信息列表并封装为多折线ECharts图表数据 * @param initialSystemOtherCollectData @@ -217,9 +216,55 @@ public class InitialSystemOtherCollectDataServiceImpl implements IInitialSystemO public Map memoryUtilizationEcharts(InitialSystemOtherCollectData initialSystemOtherCollectData) { initialSystemOtherCollectData.setCollectType(ServerLogoEnum.内存利用率.getCode()); List list = getOtherMsgSharding(initialSystemOtherCollectData); + initialSystemOtherCollectData.setCollectType(ServerLogoEnum.可用内存.getCode()); + List usedList = getOtherMsgSharding(initialSystemOtherCollectData); + InitialSystemOtherCollectData memQuery = new InitialSystemOtherCollectData(); + memQuery.setClientId(initialSystemOtherCollectData.getClientId()); + memQuery.setTableName(TableSubUtil.getTableName(DateUtils.getNowDate(), TABLE_PREFIX)); + // 总内存 + String memTotalSize = initialSystemOtherCollectDataMapper.getMemTotalSizeNoConvert(memQuery); + Double totalMemory = 0d; + if(memTotalSize != null){ + totalMemory = Double.parseDouble(memTotalSize); + } + // 将usedList转换为Map,key为createTime,value为collectValue字符串 + // 将usedList转换为Map,key为createTime,value为已用内存(GB) + Map usedMemoryGBMap = new HashMap<>(); + for (InitialSystemOtherCollectData data : usedList) { + if (data.getCreateTime() != null && data.getCollectValue() != null) { + try { + // 获取可用内存字符串(字节),防止科学计数法 + String availableMemoryStr = data.getCollectValue(); + + // 将可用内存从字节转换为GB + double availableMemory = Double.parseDouble(availableMemoryStr); + + // 计算已用内存 = 总内存 - 可用内存 + double usedMemoryGB = (totalMemory - availableMemory)/(1024 * 1024); + + // 确保已用内存不为负数 + usedMemoryGB = Math.max(0.0, usedMemoryGB); + + usedMemoryGBMap.put(data.getCreateTime(), usedMemoryGB); + } catch (NumberFormatException e) { + // 处理转换异常,可以记录日志或跳过该数据 + System.err.println("无法转换collectValue为数字: " + data.getCollectValue()); + } + } + } + // 遍历list,从Map中获取对应的已用内存值 + for (InitialSystemOtherCollectData item : list) { + Double memUsed = usedMemoryGBMap.get(item.getCreateTime()); + if (memUsed != null) { + // 格式化保留一位小数 + String formattedMemUsed = String.format("%.1f", memUsed); + item.setMemUsed(formattedMemUsed); + } + } Map> extractors = new LinkedHashMap<>(); extractors.put("memoryUtilizationData", info -> UnitChangeUtil.formatDecimal(info.getCollectValue())); + extractors.put("memoryUsedData", info -> info.getMemUsed()); return EchartsDataUtils.buildEchartsData(list, InitialSystemOtherCollectData::getCreateTime, extractors); } diff --git a/tongran-rocketmq/src/main/resources/mapper/rocketmq/InitialSystemOtherCollectDataMapper.xml b/tongran-rocketmq/src/main/resources/mapper/rocketmq/InitialSystemOtherCollectDataMapper.xml index b95f0e1..f5a6548 100644 --- a/tongran-rocketmq/src/main/resources/mapper/rocketmq/InitialSystemOtherCollectDataMapper.xml +++ b/tongran-rocketmq/src/main/resources/mapper/rocketmq/InitialSystemOtherCollectDataMapper.xml @@ -139,4 +139,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" AND d.create_time = latest.max_time AND d.collect_type='memorySizeTotalCollect' + \ No newline at end of file