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} +
+ ); + })} +
+
+ ))} +
+ )} + + + {/* 顶部工具栏 */}