From 63b01db83d9aad8a15276b4236a9a22e4aeef065 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 05 五月 2026 12:30:59 +0800
Subject: [PATCH] # Agent数据分析V3.0.1.7
---
src/main/java/com/zy/system/controller/DashboardController.java | 199 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 195 insertions(+), 4 deletions(-)
diff --git a/src/main/java/com/zy/system/controller/DashboardController.java b/src/main/java/com/zy/system/controller/DashboardController.java
index fa97e4d..974bfce 100644
--- a/src/main/java/com/zy/system/controller/DashboardController.java
+++ b/src/main/java/com/zy/system/controller/DashboardController.java
@@ -3,10 +3,15 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.core.annotations.ManagerAuth;
import com.core.common.R;
+import com.zy.ai.entity.AiAutoTuneJob;
import com.zy.ai.entity.AiChatSession;
+import com.zy.ai.entity.AiTokenUsage;
import com.zy.ai.entity.LlmCallLog;
import com.zy.ai.entity.LlmRouteConfig;
+import com.zy.ai.enums.AiPromptScene;
import com.zy.ai.mapper.AiChatSessionMapper;
+import com.zy.ai.mapper.AiTokenUsageMapper;
+import com.zy.ai.service.AiAutoTuneJobService;
import com.zy.ai.service.LlmCallLogService;
import com.zy.ai.service.LlmRouteConfigService;
import com.zy.asrs.entity.*;
@@ -25,6 +30,7 @@
import com.zy.core.thread.StationThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -58,13 +64,29 @@
@Autowired
private LlmCallLogService llmCallLogService;
@Autowired
+ private AiAutoTuneJobService aiAutoTuneJobService;
+ @Autowired
private AiChatSessionMapper aiChatSessionMapper;
+ @Autowired
+ private AiTokenUsageMapper aiTokenUsageMapper;
+ @Autowired
+ private DevicePingFileStorageService devicePingFileStorageService;
+
+ @Value("${devicePingStorage.intervalMs:1000}")
+ private int devicePingIntervalMs;
+ @Value("${devicePingStorage.timeoutMs:800}")
+ private int devicePingTimeoutMs;
+ @Value("${devicePingStorage.probeCount:3}")
+ private int devicePingProbeCount;
+ @Value("${devicePingStorage.packetSize:-1}")
+ private int devicePingPacketSize;
@GetMapping("/summary/auth")
@ManagerAuth(memo = "绯荤粺浠〃鐩樼粺璁�")
public R summary() {
Map<String, Object> tasks = buildTaskStats();
Map<String, Object> devices = buildDeviceStats();
+ Map<String, Object> network = buildNetworkStats();
Map<String, Object> ai = buildAiStats();
Map<String, Object> overview = new LinkedHashMap<>();
@@ -82,6 +104,7 @@
result.put("overview", overview);
result.put("tasks", tasks);
result.put("devices", devices);
+ result.put("network", network);
result.put("ai", ai);
return R.ok(result);
}
@@ -308,20 +331,32 @@
private Map<String, Object> buildAiStats() {
Map<String, Object> result = new LinkedHashMap<>();
+ // 浠庣嫭绔嬬疮璁¤〃璇诲彇 token 缁熻
long tokenTotal = 0L;
long promptTokenTotal = 0L;
long completionTokenTotal = 0L;
+ long llmCallCountTotal = 0L;
+ try {
+ AiTokenUsage tokenUsage = aiTokenUsageMapper.selectById(1);
+ if (tokenUsage != null) {
+ promptTokenTotal = safeCount(tokenUsage.getPromptTokens());
+ completionTokenTotal = safeCount(tokenUsage.getCompletionTokens());
+ tokenTotal = safeCount(tokenUsage.getTotalTokens());
+ llmCallCountTotal = safeCount(tokenUsage.getLlmCallCount());
+ }
+ } catch (Exception e) {
+ log.warn("dashboard ai token usage load failed: {}", safeMessage(e));
+ }
+
+ // 浼氳瘽缁熻锛堜繚鐣欑敤浜庢樉绀轰細璇濇暟鍜屾彁闂疆娆★級
long askCount = 0L;
long sessionCount = 0L;
try {
List<AiChatSession> sessions = aiChatSessionMapper.selectList(new QueryWrapper<AiChatSession>()
- .select("id", "sum_prompt_tokens", "sum_completion_tokens", "sum_total_tokens", "ask_count"));
+ .select("id", "ask_count"));
sessionCount = sessions == null ? 0L : sessions.size();
if (sessions != null) {
for (AiChatSession session : sessions) {
- promptTokenTotal += safeCount(session == null ? null : session.getSumPromptTokens());
- completionTokenTotal += safeCount(session == null ? null : session.getSumCompletionTokens());
- tokenTotal += safeCount(session == null ? null : session.getSumTotalTokens());
askCount += safeCount(session == null ? null : session.getAskCount());
}
}
@@ -401,6 +436,7 @@
overview.put("tokenTotal", tokenTotal);
overview.put("promptTokenTotal", promptTokenTotal);
overview.put("completionTokenTotal", completionTokenTotal);
+ overview.put("llmCallCountTotal", llmCallCountTotal);
overview.put("askCount", askCount);
overview.put("sessionCount", sessionCount);
overview.put("routeTotal", routeTotal);
@@ -424,6 +460,74 @@
return result;
}
+ @SuppressWarnings("unchecked")
+ private Map<String, Object> buildNetworkStats() {
+ Map<String, Object> result = new LinkedHashMap<>();
+ Map<String, Object> overview = new LinkedHashMap<>();
+ overview.put("totalDevices", 0L);
+ overview.put("okDevices", 0L);
+ overview.put("unstableDevices", 0L);
+ overview.put("offlineDevices", 0L);
+ overview.put("noDataDevices", 0L);
+ overview.put("attentionDevices", 0L);
+ overview.put("avgLatencyMs", null);
+ overview.put("maxLatencyMs", null);
+
+ Map<String, Object> samplingConfig = new LinkedHashMap<>();
+ samplingConfig.put("intervalMs", devicePingIntervalMs);
+ samplingConfig.put("timeoutMs", devicePingTimeoutMs);
+ samplingConfig.put("probeCount", devicePingProbeCount);
+ samplingConfig.put("packetSize", Math.max(devicePingPacketSize, -1));
+
+ List<Map<String, Object>> statusStats = new ArrayList<>();
+ statusStats.add(metric("姝e父", 0L));
+ statusStats.add(metric("娉㈠姩", 0L));
+ statusStats.add(metric("瓒呮椂/寮傚父", 0L));
+ statusStats.add(metric("鏆傛棤鏁版嵁", 0L));
+
+ List<Map<String, Object>> focusDevices = new ArrayList<>();
+
+ try {
+ Map<String, Object> overviewResult = devicePingFileStorageService.queryOverview(listPingConfigs());
+ Map<String, Object> summary = overviewResult.get("summary") instanceof Map
+ ? (Map<String, Object>) overviewResult.get("summary")
+ : Collections.emptyMap();
+ List<Map<String, Object>> devices = overviewResult.get("devices") instanceof List
+ ? (List<Map<String, Object>>) overviewResult.get("devices")
+ : Collections.emptyList();
+
+ long okDevices = toLong(summary.get("okDevices"));
+ long unstableDevices = toLong(summary.get("unstableDevices"));
+ long offlineDevices = toLong(summary.get("offlineDevices"));
+ long noDataDevices = toLong(summary.get("noDataDevices"));
+
+ overview.put("totalDevices", toLong(summary.get("totalDevices")));
+ overview.put("okDevices", okDevices);
+ overview.put("unstableDevices", unstableDevices);
+ overview.put("offlineDevices", offlineDevices);
+ overview.put("noDataDevices", noDataDevices);
+ overview.put("attentionDevices", unstableDevices + offlineDevices + noDataDevices);
+ overview.put("avgLatencyMs", summary.get("avgLatencyMs"));
+ overview.put("maxLatencyMs", summary.get("maxLatencyMs"));
+
+ statusStats = new ArrayList<>();
+ statusStats.add(metric("姝e父", okDevices));
+ statusStats.add(metric("娉㈠姩", unstableDevices));
+ statusStats.add(metric("瓒呮椂/寮傚父", offlineDevices));
+ statusStats.add(metric("鏆傛棤鏁版嵁", noDataDevices));
+
+ focusDevices = buildNetworkFocusDevices(devices);
+ } catch (Exception e) {
+ log.warn("dashboard network stats load failed: {}", safeMessage(e));
+ }
+
+ result.put("overview", overview);
+ result.put("samplingConfig", samplingConfig);
+ result.put("statusStats", statusStats);
+ result.put("focusDevices", focusDevices);
+ return result;
+ }
+
private List<DeviceConfig> listDeviceConfig(SlaveType type) {
try {
return deviceConfigService.list(new QueryWrapper<DeviceConfig>()
@@ -434,6 +538,93 @@
}
}
+ private List<DeviceConfig> listPingConfigs() {
+ try {
+ return deviceConfigService.list(new QueryWrapper<DeviceConfig>()
+ .isNotNull("ip")
+ .ne("ip", "")
+ .orderBy(true, true, "device_type", "device_no"));
+ } catch (Exception e) {
+ log.warn("dashboard ping device config load failed: {}", safeMessage(e));
+ return Collections.emptyList();
+ }
+ }
+
+ private List<Map<String, Object>> buildNetworkFocusDevices(List<Map<String, Object>> devices) {
+ if (devices == null || devices.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ List<Map<String, Object>> candidates = new ArrayList<>();
+ for (Map<String, Object> row : devices) {
+ if (resolveNetworkFocusRank(row) < 3) {
+ candidates.add(row);
+ }
+ }
+ if (candidates.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ candidates.sort((left, right) -> {
+ int rankDiff = Integer.compare(resolveNetworkFocusRank(left), resolveNetworkFocusRank(right));
+ if (rankDiff != 0) {
+ return rankDiff;
+ }
+ int latencyDiff = Long.compare(toLong(right.get("avgLatencyMs")), toLong(left.get("avgLatencyMs")));
+ if (latencyDiff != 0) {
+ return latencyDiff;
+ }
+ return Long.compare(toLong(right.get("latestTime")), toLong(left.get("latestTime")));
+ });
+
+ List<Map<String, Object>> result = new ArrayList<>();
+ for (Map<String, Object> item : candidates) {
+ if (item == null) {
+ continue;
+ }
+ Map<String, Object> focus = new LinkedHashMap<>();
+ focus.put("name", toText(item.get("deviceType")) + "-" + toText(item.get("deviceNo")));
+ focus.put("ip", toText(item.get("ip")));
+ focus.put("statusText", defaultText(toText(item.get("statusText")), "鏈煡"));
+ focus.put("statusType", resolveNetworkStatusTagType(toText(item.get("status"))));
+ focus.put("avgLatencyMs", item.get("avgLatencyMs"));
+ focus.put("latestTimeLabel", defaultText(toText(item.get("latestTimeLabel")), "--"));
+ focus.put("message", defaultText(toText(item.get("message")), "鏆傛棤棰濆璇存槑"));
+ result.add(focus);
+ if (result.size() >= 4) {
+ break;
+ }
+ }
+ return result;
+ }
+
+ private int resolveNetworkFocusRank(Map<String, Object> row) {
+ String status = row == null ? "" : toText(row.get("status"));
+ if ("TIMEOUT".equalsIgnoreCase(status) || "ERROR".equalsIgnoreCase(status)) {
+ return 0;
+ }
+ if ("UNSTABLE".equalsIgnoreCase(status)) {
+ return 1;
+ }
+ if ("NO_DATA".equalsIgnoreCase(status)) {
+ return 2;
+ }
+ return 3;
+ }
+
+ private String resolveNetworkStatusTagType(String status) {
+ if ("TIMEOUT".equalsIgnoreCase(status) || "ERROR".equalsIgnoreCase(status)) {
+ return "danger";
+ }
+ if ("UNSTABLE".equalsIgnoreCase(status)) {
+ return "warning";
+ }
+ if ("OK".equalsIgnoreCase(status)) {
+ return "success";
+ }
+ return "info";
+ }
+
private boolean isInboundTask(Long wrkSts) {
return wrkSts != null && wrkSts > 0 && wrkSts < 100;
}
--
Gitblit v1.9.1