From 2bf3e7c308d269beca44c0aee89e290e2e4fa504 Mon Sep 17 00:00:00 2001 From: attacker Date: Thu, 18 Jun 2026 13:26:38 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=9B=91=E6=8E=A7=E5=A4=A7=E5=B1=8F=20?= =?UTF-8?q?/grafana=E2=86=92/dashboards=20+=20Agent=E4=B8=BB=E6=9C=BATop10?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E9=9D=A2=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 路由: /grafana → /dashboards (Sidebar + App.tsx) - GrafanaDashboard 新增默认面板: Agent 主机监控 Top 10 - CPU/Memory/Disk 使用率三列排行 - 进度条颜色: >85%红 >60%黄 <60%绿 - 🥇🥈🥉 emoji 前三名 - 30s 自动刷新 - Prometheus/Zabbix/SkyWalking 需配置数据源后才可用 --- frontend/src/App.tsx | 2 +- frontend/src/components/layout/Sidebar.tsx | 2 +- .../monitor/dashboard/GrafanaDashboard.tsx | 91 ++++++++++++++++++- 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 5396182..34ac9aa 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -73,7 +73,7 @@ function App() { } /> } /> } /> - } /> + } /> } /> } /> } /> diff --git a/frontend/src/components/layout/Sidebar.tsx b/frontend/src/components/layout/Sidebar.tsx index 74f2235..7107526 100644 --- a/frontend/src/components/layout/Sidebar.tsx +++ b/frontend/src/components/layout/Sidebar.tsx @@ -88,7 +88,7 @@ const menuItems: MenuItem[] = [ children: [ { id: 'monitor-center', name: '资源监控', icon: Activity, path: '/monitor-center' }, { id: 'metrics', name: '指标监控', icon: Cpu, path: '/metrics' }, - { id: 'grafana', name: '监控大屏', icon: Monitor, path: '/grafana' }, + { id: 'grafana', name: '监控大屏', icon: Monitor, path: '/dashboards' }, { id: 'trace', name: '链路追踪', icon: GitBranch, path: '/trace' }, { id: 'alert-center', name: '告警服务', icon: Bell, path: '/alert-center' }, ], diff --git a/frontend/src/components/monitor/dashboard/GrafanaDashboard.tsx b/frontend/src/components/monitor/dashboard/GrafanaDashboard.tsx index a040799..8e4b120 100644 --- a/frontend/src/components/monitor/dashboard/GrafanaDashboard.tsx +++ b/frontend/src/components/monitor/dashboard/GrafanaDashboard.tsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'; import { Monitor, Settings, Plus, Edit, Trash2, Copy, Eye, Download, RefreshCw, Maximize2, Minimize2, Save, X, ChevronDown, BarChart3, LineChart, PieChart, - Activity, Cpu, Database, Server, Globe, Zap, AlertTriangle, TrendingUp, + Activity, Cpu, Database, Server, Globe, Zap, AlertTriangle, TrendingUp, HardDrive, TrendingDown, Clock, Calendar, Filter, Search } from 'lucide-react'; import { Button } from '@/components/ui/button'; @@ -23,6 +23,7 @@ import { toast } from 'sonner'; import { useConfirm } from '@/components/ui/confirm-dialog'; import { dashboardApi } from '@/services/api'; import { GrafanaPanelContent } from './GrafanaPanelContent'; +import { http } from '@/services/http'; interface Dashboard { id: string; @@ -107,6 +108,38 @@ const GrafanaDashboard: React.FC = () => { url: '' }); + // Agent 主机监控 — 默认面板 + const [hostTop, setHostTop] = useState([]); + useEffect(() => { + (async () => { + try { + const [cpu, mem, disk] = await Promise.all([ + http.get('/metrics/top?metric=cpu&limit=10'), + http.get('/metrics/top?metric=memory&limit=10'), + http.get('/metrics/top?metric=disk&limit=10'), + ]); + setHostTop([ + { name: 'CPU', data: Array.isArray(cpu) ? cpu : [], key: 'cpu_usage', unit: '%', icon: 'cpu' }, + { name: '内存', data: Array.isArray(mem) ? mem : [], key: 'memory_usage', unit: '%', icon: 'mem' }, + { name: '磁盘', data: Array.isArray(disk) ? disk : [], key: 'disk_usage', unit: '%', icon: 'disk' }, + ]); + } catch { /* silent */ } + })(); + const timer = setInterval(async () => { + try { + const cpu = await http.get('/metrics/top?metric=cpu&limit=10'); + const mem = await http.get('/metrics/top?metric=memory&limit=10'); + const disk = await http.get('/metrics/top?metric=disk&limit=10'); + setHostTop([ + { name: 'CPU', data: Array.isArray(cpu) ? cpu : [], key: 'cpu_usage', unit: '%', icon: 'cpu' }, + { name: '内存', data: Array.isArray(mem) ? mem : [], key: 'memory_usage', unit: '%', icon: 'mem' }, + { name: '磁盘', data: Array.isArray(disk) ? disk : [], key: 'disk_usage', unit: '%', icon: 'disk' }, + ]); + } catch { /* silent */ } + }, 30000); + return () => clearInterval(timer); + }, []); + useEffect(() => { fetchDashboards(); fetchDatasources(); @@ -253,6 +286,62 @@ const GrafanaDashboard: React.FC = () => { return (
+ {/* ===== 默认:Agent 主机监控面板 ===== */} + + +
+ + Agent 主机监控 + 默认 + 每 30s 刷新 +
+
+ + {hostTop.length === 0 ? ( +
+ +

暂无 Agent 上报数据

+

请确保至少一台主机安装了 AIOps Agent 并正常上报

+
+ ) : ( +
+ {hostTop.map((group: any) => ( +
+
+ {group.icon === 'cpu' && } + {group.icon === 'mem' && } + {group.icon === 'disk' && } + {group.name} Top 10 +
+
+ {group.data.slice(0, 10).map((h: any, i: number) => { + const val = Number(h[group.key] || 0); + const barPct = Math.min(val, 100); + const barColor = val > 85 ? 'bg-red-500' : val > 60 ? 'bg-amber-500' : 'bg-emerald-500'; + const dotColor = i < 3 ? (i === 0 ? 'text-red-400' : i === 1 ? 'text-amber-400' : 'text-orange-400') : 'text-slate-500'; + return ( +
+ + {i === 0 ? '🥇' : i === 1 ? '🥈' : i === 2 ? '🥉' : `${i + 1}`} + + + {h.hostname} + +
+
+
+ {val.toFixed(1)}{group.unit} +
+ ); + })} +
+
+ ))} +
+ )} + + + {/* 顶部工具栏 */}