feat: 重构监控中心导航,新增资源监控4大模块
- 主菜单「监控告警」→「监控中心」 - 「告警中心」→「告警服务」移至链路追踪下方 - 新增资源监控 Tab 页(主机/中间件/SNMP/站点拨测) - Agent 新增网络采集器(network)和磁盘IO采集器(diskio) - 后端扩展 Agent 上报模型,支持 NetworkStat/DiskIOStat - 前端 ServerTableRow 展示网络和磁盘IO实时指标 - WebSocket MetricsUpdate 推送扩展
This commit is contained in:
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()) ||
|
||||
|
||||
Reference in new issue
Block a user