// Prometheus 数据源面板 — 接受外部配置 // Logan.Li import React, { useState, useEffect } from 'react'; import { Server, Loader2, Activity, Cpu, RefreshCw, AlertTriangle, Container, Zap} from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { StatStrip } from '@/components/ui/stat-strip'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { prometheusProxyApi } from '@/api'; import type { JsonData } from '@/types/common'; interface Props { dsUrl?: string; } const MiniBar = ({ val, label, color }: { val: number; label: string; color?: string }) => { const pct = Math.min(val, 100); return (
{label}
); }; const fmtBytes = (b: number) => { if (!b) return '—'; if (b > 1e9) return `${(b / 1e9).toFixed(1)} GB`; if (b > 1e6) return `${(b / 1e6).toFixed(1)} MB`; return `${(b / 1e3).toFixed(1)} KB`; }; const fmtBps = (b: number) => { if (!b) return '—'; if (b > 1e9) return `${(b / 1e9).toFixed(1)} GB/s`; if (b > 1e6) return `${(b / 1e6).toFixed(1)} MB/s`; if (b > 1e3) return `${(b / 1e3).toFixed(1)} KB/s`; return `${b.toFixed(1)} B/s`; }; function parsePrune( result: JsonData[]): JsonData[] { return (result || []).map((r: JsonData) => { const m: JsonData = { ...(r.metric || {}) }; if (r.value) m.value = r.value[1]; return m; }); } const Box = (p: JsonData) => ; const K8sPanel: React.FC<{ d: JsonData}> = ({ d }) => (
节点 CPU / 内存利用率
{(d.nodeCPU || []).map((n: JsonData, i: number) => { const mem = (d.nodeMem || []).find((m: JsonData) => m.node === n.node); return
{n.node}
; })}
); const NodePanel: React.FC<{ d: JsonData}> = ({ d }) => (
{(d.nodes || []).map((n: JsonData, i: number) => { const inst = n.instance || n.exported_instance || ''; const cpu = (d.cpuUsage||[]).find((x: JsonData)=>x.instance===inst); const mem = (d.memUsage||[]).find((x: JsonData)=>x.instance===inst); const disk = (d.diskUsage||[]).find((x: JsonData)=>x.instance===inst); const up = (d.up||[]).find((x: JsonData)=>x.instance===inst); const rx = (d.netRx||[]).find((x: JsonData)=>x.instance===inst); const tx = (d.netTx||[]).find((x: JsonData)=>x.instance===inst); return ; })}
节点状态CPU内存磁盘流入流出
{n.nodename||inst} {up?.value===1?'UP':'DOWN'} {fmtBps(Number(rx?.value||0))} {fmtBps(Number(tx?.value||0))}
); const PodPanel: React.FC<{ d: JsonData}> = ({ d }) => (
CPU Top 10
{(d.cpuTop||[]).map((p: JsonData, i:number)=>
{i+1}{p.pod}
)}
内存 Top 10
{(d.memTop||[]).map((p: JsonData, i:number)=>
{i+1}{p.pod}{fmtBytes(Number(p.value||0))}
)}
); const JvmPanel: React.FC<{ d: JsonData}> = ({ d }) => { const h = Number(d.heapUsed?.[0]?.value||0); const uptime = Number(d.uptime?.[0]?.value||0); return (
{uptime>86400?`${(uptime/86400).toFixed(1)}d`:`${(uptime/3600).toFixed(1)}h`}
Uptime
80?'bg-orange-500':'bg-purple-500'} />
Heap
Non-Heap
{d.threadCount?.[0]?.value||0}
Threads
{Number(d.gcPause?.[0]?.value||0).toFixed(3)}
GC Pause (s)
); }; export const PrometheusDashboard: React.FC = ({ dsUrl }) => { const [connected, setConnected] = useState(false); const [loading, setLoading] = useState(false); const [targets, setTargets] = useState(0); const [error, setError] = useState(''); const [tab, setTab] = useState('kubernetes'); const [k8sD, setK8sD] = useState({}); const [nodeD, setNodeD] = useState({}); const [podD, setPodD] = useState({}); const [jvmD, setJvmD] = useState({}); useEffect(() => { if (dsUrl) doConnect(dsUrl); }, [dsUrl]); const doConnect = async (u: string) => { setLoading(true); setError(''); try { const data: JsonData = await prometheusProxyApi.connect(u); setConnected(true); setTargets(data.targets||0); loadAll(u); } catch (e) { setConnected(false); setError((e as JsonData).message||'连接失败'); } finally { setLoading(false); } }; const loadAll = async (u: string) => { for (const t of ['kubernetes','node','pod','jvm']) { try { const data: JsonData = await prometheusProxyApi.dashboard(u, t); const items: JsonData = {}; for (const [k, v] of Object.entries(data||{})) items[k] = Array.isArray(v) ? v : ((v as JsonData)?.data?.result ? parsePrune((v as JsonData).data.result) : v); if (t==='kubernetes') setK8sD(items); if (t==='node') setNodeD(items); if (t==='pod') setPodD(items); if (t==='jvm') setJvmD(items); } catch {} } }; const refresh = () => { if (dsUrl) doConnect(dsUrl); }; if (!connected && !error) return null; return (
Prometheus 监控 {connected && {targets} targets} {connected &&
}
{loading ? (

连接中…

) : error ? (
{error}
) : ( Kubernetes Node Pod JVM )}
); }; export default PrometheusDashboard;