// 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 (
);
};
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 }) => (
| 节点 | 状态 | CPU | 内存 | 磁盘 | 流入 | 流出 |
{(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
| {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 ? ()
: (
Kubernetes
Node
Pod
JVM
)}
);
};
export default PrometheusDashboard;