feat: 重构监控中心导航,新增资源监控4大模块

- 主菜单「监控告警」→「监控中心」
- 「告警中心」→「告警服务」移至链路追踪下方
- 新增资源监控 Tab 页(主机/中间件/SNMP/站点拨测)
- Agent 新增网络采集器(network)和磁盘IO采集器(diskio)
- 后端扩展 Agent 上报模型,支持 NetworkStat/DiskIOStat
- 前端 ServerTableRow 展示网络和磁盘IO实时指标
- WebSocket MetricsUpdate 推送扩展
This commit is contained in:
attacker committed 2026-06-18 09:30:45 +00:00
1 parent 020b7a9063
commit f3a9e5e8d0
21 files changed
+1007 -32

No files matched your search

@@ -1,4 +1,4 @@
import { useState, useEffect } from 'react';
import { useState, useEffect, useRef } from 'react';
import { cn } from '@/lib/utils';
import { Card, CardContent } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
@@ -168,6 +168,82 @@ export function ServerManager() {
loadData();
}, []);
// WebSocket 实时接收 Agent 指标推送 // Logan.Li
const wsRef = useRef<WebSocket | null>(null);
const reconnectTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
useEffect(() => {
const token = useUserStore.getState().token;
if (!token) return;
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsUrl = `${protocol}//${window.location.host}/ws/metrics?token=${token}`;
const connect = () => {
if (wsRef.current?.readyState === WebSocket.OPEN) return;
const ws = new WebSocket(wsUrl);
wsRef.current = ws;
ws.onopen = () => {
console.log('[MetricsWS] 已连接,实时接收指标推送');
};
ws.onmessage = (event) => {
try {
const msg = JSON.parse(event.data);
if (msg.type === 'metrics_update') {
setServers((prev) =>
prev.map((s) => {
// 通过 hostname 匹配(Agent 上报时使用 hostname)
if (s.hostname === msg.hostname) {
return {
...s,
cpu_usage: msg.cpu_usage,
memory_usage: msg.memory_usage,
disk_usage: msg.disk_usage,
status: msg.status,
tcp_established: msg.tcp_established,
tcp_time_wait: msg.tcp_time_wait,
net_rx_bps: msg.net_rx_bps,
net_tx_bps: msg.net_tx_bps,
disk_read_bps: msg.disk_read_bps,
disk_write_bps: msg.disk_write_bps,
};
}
return s;
})
);
}
} catch (e) {
// 忽略非 JSON 消息
}
};
ws.onclose = () => {
console.log('[MetricsWS] 连接断开,3 秒后重连');
wsRef.current = null;
reconnectTimerRef.current = setTimeout(connect, 3000);
};
ws.onerror = (err) => {
console.error('[MetricsWS] 连接错误:', err);
ws.close();
};
};
connect();
return () => {
if (reconnectTimerRef.current) clearTimeout(reconnectTimerRef.current);
if (wsRef.current) {
wsRef.current.onclose = null; // 阻止自动重连
wsRef.current.close();
wsRef.current = null;
}
};
}, []);
const filteredServers = servers.filter((server) => {
const matchesSearch =
(server.hostname || '').toLowerCase().includes(searchQuery.toLowerCase()) ||