add gpuusage的逻辑
Change-Id: Ie1634a7d58ab94b05a3ebd7de87d362ca9be2286
diff --git a/Merge/front/src/api/posts_trm.js b/Merge/front/src/api/posts_trm.js
index d6303a7..8f7e877 100644
--- a/Merge/front/src/api/posts_trm.js
+++ b/Merge/front/src/api/posts_trm.js
@@ -209,4 +209,30 @@
}
console.log('Normalized sys cost list:', list)
return list
+}
+
+/**
+ * 获取GPU使用情况数据
+ * GET /gpu-usage
+ * @param {number} limit 获取记录条数,默认100条
+ * @returns Promise<[ {id, gpu_id, gpu_usage, gpu_memory_usage, timestamp}, … ]>
+ */
+export async function fetchGpuUsage(limit = 100) {
+ const token = localStorage.getItem('token')
+ const res = await fetch(`http://10.126.59.25:8082/gpu-usage?limit=${limit}`, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${token}`
+ }
+ })
+ if (!res.ok) throw new Error(`fetchGpuUsage: ${res.status}`)
+ const json = await res.json()
+ console.log('fetchGpuUsage response:', json)
+
+ if (json.success === false) {
+ throw new Error(json.message || 'Failed to fetch GPU usage')
+ }
+
+ return json.data?.records || []
}
\ No newline at end of file
diff --git a/Merge/front/src/components/PerformanceLogs.js b/Merge/front/src/components/PerformanceLogs.js
index f87ef7a..67518de 100644
--- a/Merge/front/src/components/PerformanceLogs.js
+++ b/Merge/front/src/components/PerformanceLogs.js
@@ -3,16 +3,19 @@
ResponsiveContainer, LineChart, Line,
XAxis, YAxis, Tooltip, CartesianGrid, Legend
} from 'recharts';
-import { fetchSysCost } from '../api/posts_trm';
+import { fetchSysCost, fetchGpuUsage } from '../api/posts_trm';
function PerformanceLogs({ userId }) {
const [data, setData] = useState([]);
+ const [gpuData, setGpuData] = useState([]);
const [loading, setLoading] = useState(true);
const [unauthorized, setUnauthorized] = useState(false);
useEffect(() => {
setLoading(true);
- fetchSysCost(userId)
+
+ // 获取系统性能数据
+ const fetchSystemData = fetchSysCost(userId)
.then(result => {
// 检查是否是权限错误
if (result && result.status === 'error' && result.message === 'Unauthorized') {
@@ -49,10 +52,59 @@
setUnauthorized(true);
setData([]);
}
+ });
+
+ // 获取GPU数据
+ const fetchGpuData = fetchGpuUsage(100)
+ .then(result => {
+ console.log('GPU data:', result);
+ const processedData = processGpuData(result);
+ setGpuData(processedData);
})
+ .catch(err => {
+ console.error('fetchGpuUsage error:', err);
+ });
+
+ Promise.all([fetchSystemData, fetchGpuData])
.finally(() => setLoading(false));
}, [userId]);
+ // 处理GPU数据,按时间戳分组
+ const processGpuData = (rawData) => {
+ const timeMap = new Map();
+
+ rawData.forEach(record => {
+ const timestamp = new Date(record.timestamp).getTime();
+ if (!timeMap.has(timestamp)) {
+ timeMap.set(timestamp, { timestamp });
+ }
+ const timeEntry = timeMap.get(timestamp);
+ timeEntry[`gpu${record.gpu_id}_usage`] = record.gpu_usage;
+ timeEntry[`gpu${record.gpu_id}_memory`] = record.gpu_memory_usage;
+ });
+
+ return Array.from(timeMap.values()).sort((a, b) => a.timestamp - b.timestamp);
+ };
+
+ // 获取GPU颜色
+ const getGpuColors = () => {
+ return ['#8884d8', '#82ca9d', '#ffc658', '#ff7300', '#8dd1e1', '#d084d0', '#ffb347', '#87ceeb'];
+ };
+
+ // 获取唯一的GPU ID列表
+ const getGpuIds = () => {
+ const ids = new Set();
+ gpuData.forEach(entry => {
+ Object.keys(entry).forEach(key => {
+ if (key.includes('gpu') && key.includes('_usage')) {
+ const gpuId = key.replace('_usage', '').replace('gpu', '');
+ ids.add(gpuId);
+ }
+ });
+ });
+ return Array.from(ids).sort((a, b) => parseInt(a) - parseInt(b));
+ };
+
if (loading) {
return (
<section className="dashboard-performance">
@@ -114,6 +166,70 @@
return (
<section className="dashboard-performance">
+ {/* GPU使用率图表 */}
+ <div style={{ marginBottom: '30px' }}>
+ <h3>GPU 使用率</h3>
+ <ResponsiveContainer width="100%" height={300}>
+ <LineChart data={gpuData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
+ <CartesianGrid strokeDasharray="3 3" />
+ <XAxis
+ dataKey="timestamp"
+ type="number"
+ domain={['dataMin', 'dataMax']}
+ tickFormatter={ts => new Date(ts).toLocaleTimeString()}
+ />
+ <YAxis domain={[0, 100]} label={{ value: '使用率 (%)', angle: -90, position: 'insideLeft' }} />
+ <Tooltip
+ formatter={(val, name) => [`${val?.toFixed(2)}%`, name]}
+ labelFormatter={ts => new Date(ts).toLocaleString()}
+ />
+ <Legend />
+ {getGpuIds().map((gpuId, index) => (
+ <Line
+ key={`gpu${gpuId}_usage`}
+ type="monotone"
+ dataKey={`gpu${gpuId}_usage`}
+ stroke={getGpuColors()[index % getGpuColors().length]}
+ name={`GPU ${gpuId} 使用率`}
+ connectNulls={false}
+ />
+ ))}
+ </LineChart>
+ </ResponsiveContainer>
+ </div>
+
+ {/* GPU内存占用图表 */}
+ <div style={{ marginBottom: '30px' }}>
+ <h3>GPU 内存占用</h3>
+ <ResponsiveContainer width="100%" height={300}>
+ <LineChart data={gpuData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
+ <CartesianGrid strokeDasharray="3 3" />
+ <XAxis
+ dataKey="timestamp"
+ type="number"
+ domain={['dataMin', 'dataMax']}
+ tickFormatter={ts => new Date(ts).toLocaleTimeString()}
+ />
+ <YAxis domain={[0, 'auto']} label={{ value: '内存 (MB)', angle: -90, position: 'insideLeft' }} />
+ <Tooltip
+ formatter={(val, name) => [`${val?.toFixed(2)} MB`, name]}
+ labelFormatter={ts => new Date(ts).toLocaleString()}
+ />
+ <Legend />
+ {getGpuIds().map((gpuId, index) => (
+ <Line
+ key={`gpu${gpuId}_memory`}
+ type="monotone"
+ dataKey={`gpu${gpuId}_memory`}
+ stroke={getGpuColors()[index % getGpuColors().length]}
+ name={`GPU ${gpuId} 内存`}
+ connectNulls={false}
+ />
+ ))}
+ </LineChart>
+ </ResponsiveContainer>
+ </div>
+
{/* 响应时间图表 */}
<div style={{ marginBottom: '30px' }}>
<h3>响应时间</h3>