diff --git a/frontend/src/pages/System/Metrics/Dashboard/index.tsx b/frontend/src/pages/System/Metrics/Dashboard/index.tsx index 7dfc96b5..725bed10 100644 --- a/frontend/src/pages/System/Metrics/Dashboard/index.tsx +++ b/frontend/src/pages/System/Metrics/Dashboard/index.tsx @@ -188,9 +188,40 @@ const MetricsDashboard: React.FC = () => { process: formatPercent(metrics.cpu.processCpu * 100) + '%', }, memory: { - heapUsed: formatBytes(metrics.memory.heapUsed), - heapMax: formatBytes(metrics.memory.heapMax), - heapPercent: formatPercent(metrics.memory.heapPercent) + '%', + heap: { + used: formatBytes(metrics.memory.heapUsed), + max: formatBytes(metrics.memory.heapMax), + committed: formatBytes(metrics.memory.heapCommitted), + percent: formatPercent(metrics.memory.heapPercent) + '%', + }, + nonHeap: { + used: formatBytes(metrics.memory.nonHeapUsed), + max: formatBytes(metrics.memory.nonHeapMax), + committed: formatBytes(metrics.memory.nonHeapCommitted), + percent: formatPercent(metrics.memory.nonHeapPercent) + '%', + }, + regions: metrics.memory.regions ? { + eden: metrics.memory.regions.eden ? { + used: formatBytes(metrics.memory.regions.eden.used), + max: formatBytes(metrics.memory.regions.eden.max), + committed: formatBytes(metrics.memory.regions.eden.committed), + } : null, + oldGen: metrics.memory.regions.oldGen ? { + used: formatBytes(metrics.memory.regions.oldGen.used), + max: formatBytes(metrics.memory.regions.oldGen.max), + committed: formatBytes(metrics.memory.regions.oldGen.committed), + } : null, + survivor: metrics.memory.regions.survivor ? { + used: formatBytes(metrics.memory.regions.survivor.used), + max: formatBytes(metrics.memory.regions.survivor.max), + committed: formatBytes(metrics.memory.regions.survivor.committed), + } : null, + metaspace: metrics.memory.regions.metaspace ? { + used: formatBytes(metrics.memory.regions.metaspace.used), + max: formatBytes(metrics.memory.regions.metaspace.max), + committed: formatBytes(metrics.memory.regions.metaspace.committed), + } : null, + } : null, }, threads: metrics.threads, hikari: metrics.hikari, @@ -350,8 +381,9 @@ const MetricsDashboard: React.FC = () => {
{formatBytes(metrics.memory.heapUsed)}
-
- / {formatBytes(metrics.memory.heapMax)} +
+
最大: {formatBytes(metrics.memory.heapMax)}
+
已分配: {formatBytes(metrics.memory.heapCommitted)}
{memoryPercent >= THRESHOLDS.memory.warning && ( @@ -549,6 +581,118 @@ const MetricsDashboard: React.FC = () => {
+ {/* 内存区域详情(如果可用) */} + {metrics.memory.regions && ( + + + JVM 内存区域详情 + + +
+ {/* Eden 区 */} + {metrics.memory.regions.eden && ( +
+
Eden 区(年轻代)
+
+
+ 已使用: + {formatBytes(metrics.memory.regions.eden.used)} +
+
+ 已分配: + {formatBytes(metrics.memory.regions.eden.committed)} +
+
+ 最大: + {formatBytes(metrics.memory.regions.eden.max)} +
+ +
+
+ )} + + {/* Old Gen */} + {metrics.memory.regions.oldGen && ( +
+
Old Gen(老年代)
+
+
+ 已使用: + {formatBytes(metrics.memory.regions.oldGen.used)} +
+
+ 已分配: + {formatBytes(metrics.memory.regions.oldGen.committed)} +
+
+ 最大: + {formatBytes(metrics.memory.regions.oldGen.max)} +
+ +
+
+ )} + + {/* Survivor 区 */} + {metrics.memory.regions.survivor && ( +
+
Survivor 区
+
+
+ 已使用: + {formatBytes(metrics.memory.regions.survivor.used)} +
+
+ 已分配: + {formatBytes(metrics.memory.regions.survivor.committed)} +
+
+ 最大: + {formatBytes(metrics.memory.regions.survivor.max)} +
+ +
+
+ )} + + {/* Metaspace */} + {metrics.memory.regions.metaspace && ( +
+
Metaspace(元空间)
+
+
+ 已使用: + {formatBytes(metrics.memory.regions.metaspace.used)} +
+
+ 已分配: + {formatBytes(metrics.memory.regions.metaspace.committed)} +
+
+ 最大: + {formatBytes(metrics.memory.regions.metaspace.max)} +
+ +
+
+ )} +
+
+
+ )} + {/* GC 统计 */} diff --git a/frontend/src/pages/System/Metrics/Dashboard/service.ts b/frontend/src/pages/System/Metrics/Dashboard/service.ts index 2a5f8548..946fdc93 100644 --- a/frontend/src/pages/System/Metrics/Dashboard/service.ts +++ b/frontend/src/pages/System/Metrics/Dashboard/service.ts @@ -42,28 +42,95 @@ export const getMetric = (metricName: string, tag?: string) => { }; /** - * 获取 JVM 内存信息 + * 获取 JVM 内存信息(增强版:包含 committed 和区域详情) */ export const getJvmMemory = async (): Promise => { - const [heapUsedRes, heapMaxRes, nonHeapUsedRes, nonHeapMaxRes] = await Promise.all([ + // 基础堆和非堆内存指标 + const [ + heapUsedRes, + heapMaxRes, + heapCommittedRes, + nonHeapUsedRes, + nonHeapMaxRes, + nonHeapCommittedRes + ] = await Promise.all([ getMetric('jvm.memory.used', 'area:heap'), getMetric('jvm.memory.max', 'area:heap'), + getMetric('jvm.memory.committed', 'area:heap'), getMetric('jvm.memory.used', 'area:nonheap'), getMetric('jvm.memory.max', 'area:nonheap'), + getMetric('jvm.memory.committed', 'area:nonheap'), ]); const heapUsed = heapUsedRes.measurements[0].value; const heapMax = heapMaxRes.measurements[0].value; + const heapCommitted = heapCommittedRes.measurements[0].value; const nonHeapUsed = nonHeapUsedRes.measurements[0].value; const nonHeapMax = nonHeapMaxRes.measurements[0].value; + const nonHeapCommitted = nonHeapCommittedRes.measurements[0].value; + + // 尝试获取详细区域信息(可能因GC类型不同而失败) + let regions; + try { + const [edenUsed, edenMax, edenCommitted, oldUsed, oldMax, oldCommitted, + survivorUsed, survivorMax, survivorCommitted, metaspaceUsed, metaspaceMax, metaspaceCommitted] = + await Promise.all([ + // Eden 区 + getMetric('jvm.memory.used', 'id:G1 Eden Space').catch(() => null), + getMetric('jvm.memory.max', 'id:G1 Eden Space').catch(() => null), + getMetric('jvm.memory.committed', 'id:G1 Eden Space').catch(() => null), + // Old Gen + getMetric('jvm.memory.used', 'id:G1 Old Gen').catch(() => null), + getMetric('jvm.memory.max', 'id:G1 Old Gen').catch(() => null), + getMetric('jvm.memory.committed', 'id:G1 Old Gen').catch(() => null), + // Survivor + getMetric('jvm.memory.used', 'id:G1 Survivor Space').catch(() => null), + getMetric('jvm.memory.max', 'id:G1 Survivor Space').catch(() => null), + getMetric('jvm.memory.committed', 'id:G1 Survivor Space').catch(() => null), + // Metaspace + getMetric('jvm.memory.used', 'id:Metaspace').catch(() => null), + getMetric('jvm.memory.max', 'id:Metaspace').catch(() => null), + getMetric('jvm.memory.committed', 'id:Metaspace').catch(() => null), + ]); + + regions = { + eden: edenUsed && edenMax && edenCommitted ? { + used: edenUsed.measurements[0].value, + max: edenMax.measurements[0].value, + committed: edenCommitted.measurements[0].value, + } : undefined, + oldGen: oldUsed && oldMax && oldCommitted ? { + used: oldUsed.measurements[0].value, + max: oldMax.measurements[0].value, + committed: oldCommitted.measurements[0].value, + } : undefined, + survivor: survivorUsed && survivorMax && survivorCommitted ? { + used: survivorUsed.measurements[0].value, + max: survivorMax.measurements[0].value, + committed: survivorCommitted.measurements[0].value, + } : undefined, + metaspace: metaspaceUsed && metaspaceMax && metaspaceCommitted ? { + used: metaspaceUsed.measurements[0].value, + max: metaspaceMax.measurements[0].value, + committed: metaspaceCommitted.measurements[0].value, + } : undefined, + }; + } catch (error) { + // 如果区域详情获取失败(可能是非G1 GC),忽略错误 + console.debug('无法获取内存区域详情,可能使用了非G1 GC收集器'); + regions = undefined; + } return { heapUsed, heapMax, + heapCommitted, heapPercent: (heapUsed / heapMax) * 100, nonHeapUsed, nonHeapMax, + nonHeapCommitted, nonHeapPercent: (nonHeapUsed / nonHeapMax) * 100, + regions, }; }; @@ -232,9 +299,11 @@ export const getAllMetrics = async (): Promise => { memory: memoryResult.status === 'fulfilled' ? memoryResult.value : { heapUsed: 0, heapMax: 0, + heapCommitted: 0, heapPercent: 0, nonHeapUsed: 0, nonHeapMax: 0, + nonHeapCommitted: 0, nonHeapPercent: 0, }, cpu: cpuResult.status === 'fulfilled' ? cpuResult.value : { systemCpu: 0, processCpu: 0 }, diff --git a/frontend/src/pages/System/Metrics/Dashboard/types.ts b/frontend/src/pages/System/Metrics/Dashboard/types.ts index 38c5dd98..f0d1bc82 100644 --- a/frontend/src/pages/System/Metrics/Dashboard/types.ts +++ b/frontend/src/pages/System/Metrics/Dashboard/types.ts @@ -49,16 +49,34 @@ export interface MetricResponse { }>; } +/** + * JVM 内存区域详情 + */ +export interface MemoryRegion { + used: number; // 已使用(字节) + max: number; // 最大值(字节) + committed: number; // 已分配(字节) +} + /** * JVM 内存信息 */ export interface JvmMemoryInfo { heapUsed: number; // 堆内存使用量(字节) heapMax: number; // 堆内存最大值(字节) + heapCommitted: number; // 堆内存已分配(字节) heapPercent: number; // 堆内存使用百分比 nonHeapUsed: number; // 非堆内存使用量(字节) nonHeapMax: number; // 非堆内存最大值(字节) + nonHeapCommitted: number; // 非堆内存已分配(字节) nonHeapPercent: number; // 非堆内存使用百分比 + // 详细区域信息(可选) + regions?: { + eden?: MemoryRegion; // Eden 区(年轻代) + oldGen?: MemoryRegion; // Old Gen(老年代) + survivor?: MemoryRegion; // Survivor 区 + metaspace?: MemoryRegion; // Metaspace(元空间) + }; } /**