import type { ServerMetrics } from '../../types'; import { formatBytes, formatUptime, formatPercent, formatLatencyMs } from '../../utils/format'; import './ServerDetail.css'; interface ServerDetailProps { metrics: ServerMetrics; serverName: string; onClose: () => void; } export const ServerDetail = ({ metrics, serverName, onClose }: ServerDetailProps) => { return (
e.stopPropagation()}>

{serverName} - 详细信息

系统与环境

{/* 系统基本信息 */}

基本信息

主机名 {metrics.hostname}
操作系统 {metrics.os.distro}
架构 {metrics.os.architecture}
内核版本 {metrics.os.kernel}
{/* 运行时信息 */}

运行时信息

运行时间 {formatUptime(metrics.uptimeSeconds)}
进程数量 {metrics.system.processCount}
{metrics.system.loggedInUsers !== undefined && (
登录会话 {metrics.system.loggedInUsers}
)} {metrics.system.tcpConnections !== undefined && (
TCP 连接数 {metrics.system.tcpConnections}
)} {metrics.system.packageCount > 0 && (
已安装软件包 {metrics.system.packageCount} ({metrics.system.packageManager})
)}
{/* 性能指标 */}

性能指标

磁盘读取 {metrics.system.diskReadSpeed.toFixed(2)} MB/s
磁盘写入 {metrics.system.diskWriteSpeed.toFixed(2)} MB/s
{metrics.system.temperature && metrics.system.temperature > 0 && (
系统温度 {metrics.system.temperature.toFixed(1)}°C
)} {(metrics.system.networkRxSpeed !== undefined || metrics.system.networkTxSpeed !== undefined) && ( <>
网络下载 {(metrics.system.networkRxSpeed || 0).toFixed(2)} MB/s
网络上传 {(metrics.system.networkTxSpeed || 0).toFixed(2)} MB/s
)}
{/* 延迟信息 */} {metrics.latency && (

网络延迟(采集端测量)

下列指标均在采集器所在机器上探测:第一项为到监控中心 gRPC 地址的 TCP 建连时间;外网三项为采集端对公网站点的 TCP(:80 / :443)建连耗时,非 ICMP ping。

采集器到监控中心 与 CENTRAL_GRPC 的 TCP 连通 {formatLatencyMs(metrics.latency.clientToServer)}
{metrics.latency.external && ( <>
百度 (baidu.com) 采集端 TCP 探测 {metrics.latency.external['baidu.com'] || '超时'}
谷歌 (google.com) 采集端 TCP 探测 {metrics.latency.external['google.com'] || '超时'}
GitHub (github.com) 采集端 TCP 探测 {metrics.latency.external['github.com'] || '超时'}
)}
)}

处理器与内存

处理器

型号 {metrics.cpu.model}
核心数 {metrics.cpu.cores}
使用率 {formatPercent(metrics.cpu.usagePercent)}
{metrics.cpu.temperature && metrics.cpu.temperature > 0 && (
温度 {metrics.cpu.temperature.toFixed(1)}°C
)} {metrics.cpu.loadAverages && metrics.cpu.loadAverages.length > 0 && ( <>
负载 (1 / 5 / 15 min) {metrics.cpu.loadAverages.map((l) => l.toFixed(2)).join(' / ')}
{metrics.cpu.cores > 0 && (
相对核心(1 min 负载) {formatPercent(Math.min((metrics.cpu.loadAverages[0] / metrics.cpu.cores) * 100, 100))}{' '} ({metrics.cpu.loadAverages[0].toFixed(2)} / {metrics.cpu.cores} 核)
)} )}
{metrics.cpu.perCoreUsage && metrics.cpu.perCoreUsage.length > 0 && (

各核心使用率

{metrics.cpu.perCoreUsage.map((core) => (
核心 {core.core} {formatPercent(core.percent)}
))}
)}

内存

使用率 {formatPercent(metrics.memory.usedPercent)}
总容量 {formatBytes(metrics.memory.totalBytes)}
已使用 {formatBytes(metrics.memory.usedBytes)}
可用 {formatBytes(metrics.memory.freeBytes)}
{(metrics.memory.swapTotalBytes !== undefined || metrics.memory.swapType !== undefined) && ( <>
Swap 总量 {formatBytes(metrics.memory.swapTotalBytes ?? 0)}
Swap 已用 {formatBytes(metrics.memory.swapUsedBytes ?? 0)} {metrics.memory.swapUsedPercent !== undefined && ( ({formatPercent(metrics.memory.swapUsedPercent)}) )}
Swap 可用 {formatBytes(metrics.memory.swapFreeBytes ?? 0)}
Swap 类型 {metrics.memory.swapType ?? '—'}
)}

存储与磁盘

    {metrics.storage.map((disk, index) => (
  • {disk.mount} {formatPercent(disk.usedPercent)}
    已用 {formatBytes(disk.usedBytes)} / 共 {formatBytes(disk.totalBytes)} · 可用{' '} {formatBytes(disk.freeBytes)}
  • ))}
{metrics.gpu && metrics.gpu.length > 0 && metrics.gpu[0].status !== 'not_available' && (

图形设备

{metrics.gpu.map((gpu, index) => (
{gpu.name} {gpu.status}
利用率 {formatPercent(gpu.utilizationPercent)}
显存总量 {gpu.memoryTotalMB} MB
显存使用 {gpu.memoryUsedMB} MB
{gpu.temperature && gpu.temperature > 0 && (
温度 {gpu.temperature.toFixed(1)}°C
)}
))}
)} {metrics.network && metrics.network.length > 0 && (

网络

接口 IP MAC 接收 发送
{metrics.network.map((iface, index) => (
{iface.name} {iface.ipAddress && iface.ipAddress !== 'N/A' ? iface.ipAddress : '—'} {iface.macAddress || '—'} {formatBytes(iface.rxBytes)} {formatBytes(iface.txBytes)}
))}
)} {((metrics.system.topProcesses && metrics.system.topProcesses.length > 0) || (metrics.system.dockerStats && metrics.system.dockerStats.available)) && (

进程与服务

{metrics.system.topProcesses && metrics.system.topProcesses.length > 0 && (

资源占用较高的进程(前 10)

# 进程 PID CPU 内存
{metrics.system.topProcesses.map((proc, index) => (
{index + 1} {proc.name} {proc.pid} {proc.cpu}% {proc.memory}% {proc.memoryMB.toFixed(1)} MB
))}
)} {metrics.system.dockerStats && metrics.system.dockerStats.available && (

Docker

{metrics.system.dockerStats.version && (
Docker 版本 {metrics.system.dockerStats.version}
运行中的容器 {metrics.system.dockerStats.running}
停止的容器 {metrics.system.dockerStats.stopped}
镜像数量 {metrics.system.dockerStats.imageCount}
)} {metrics.system.dockerStats.runningNames && metrics.system.dockerStats.runningNames.length > 0 && (

运行中的容器

{metrics.system.dockerStats.runningNames.map((name, index) => ( {name} ))}
)} {metrics.system.dockerStats.stoppedNames && metrics.system.dockerStats.stoppedNames.length > 0 && (

停止的容器

{metrics.system.dockerStats.stoppedNames.map((name, index) => ( {name} ))}
)} {metrics.system.dockerStats.imageNames && metrics.system.dockerStats.imageNames.length > 0 && (

镜像列表

{metrics.system.dockerStats.imageNames.map((name, index) => ( {name} ))}
)}
)}
)} {metrics.system.systemLogs && metrics.system.systemLogs.length > 0 && (

诊断与日志

系统日志

{metrics.system.systemLogs.map((log, index) => (
{log}
))}
)}
); };