blob: 00f7e7d7a9d59ea570f120ceec70ce8e61ac3ad6 [file] [log] [blame]
TRM-coding85e5c322025-06-18 19:49:21 +08001import React, { useState, useEffect } from 'react';
2import {
3 ResponsiveContainer, LineChart, Line,
4 XAxis, YAxis, Tooltip, CartesianGrid, Legend
5} from 'recharts';
6import { fetchSysCost } from '../api/posts_trm';
7
8function PerformanceLogs({ userId }) {
9 const [data, setData] = useState([]);
TRM-coding2a8fd602025-06-19 19:33:16 +080010 const [loading, setLoading] = useState(true);
TRM-coding85e5c322025-06-18 19:49:21 +080011
12 useEffect(() => {
TRM-coding2a8fd602025-06-19 19:33:16 +080013 setLoading(true);
TRM-coding85e5c322025-06-18 19:49:21 +080014 fetchSysCost(userId)
TRM-coding882dc442025-06-18 20:13:21 +080015 .then(list => {
16 const msList = list.map(item => ({
17 ...item,
18 elapsed_time: item.elapsed_time * 1000,
19 cpu_user: item.cpu_user * 1000,
20 cpu_system: item.cpu_system * 1000,
21 memory_rss: item.memory_rss / (1024 * 1024*8), // convert bytes to MB
22 record_time_ts: new Date(item.record_time).getTime() // add numeric timestamp
23 }));
24 console.log('Converted data:', msList[0]); // debug first item
25 setData(msList);
26 })
TRM-coding2a8fd602025-06-19 19:33:16 +080027 .catch(err => console.error('fetchSysCost error:', err))
28 .finally(() => setLoading(false));
TRM-coding85e5c322025-06-18 19:49:21 +080029 }, [userId]);
30
TRM-coding2a8fd602025-06-19 19:33:16 +080031 if (loading) {
32 return (
33 <section className="dashboard-performance">
34 <div style={{
35 display: 'flex',
36 justifyContent: 'center',
37 alignItems: 'center',
38 height: '400px',
39 flexDirection: 'column'
40 }}>
41 <div style={{
42 border: '4px solid #f3f3f3',
43 borderTop: '4px solid #3498db',
44 borderRadius: '50%',
45 width: '50px',
46 height: '50px',
47 animation: 'spin 1s linear infinite'
48 }}></div>
49 <p style={{ marginTop: '20px', color: '#666' }}>加载中...</p>
50 <style>{`
51 @keyframes spin {
52 0% { transform: rotate(0deg); }
53 100% { transform: rotate(360deg); }
54 }
55 `}</style>
56 </div>
57 </section>
58 );
59 }
60
TRM-coding85e5c322025-06-18 19:49:21 +080061 return (
62 <section className="dashboard-performance">
TRM-coding882dc442025-06-18 20:13:21 +080063 {/* 响应时间图表 */}
64 <div style={{ marginBottom: '30px' }}>
65 <h3>响应时间</h3>
66 <ResponsiveContainer width="100%" height={300}>
67 <LineChart data={data} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
68 <CartesianGrid strokeDasharray="3 3" />
69 <XAxis
70 dataKey="record_time_ts"
71 type="number"
72 domain={['dataMin', 'dataMax']}
73 tickFormatter={ts => new Date(ts).toLocaleTimeString()}
74 />
75 <YAxis domain={[0, 'auto']} label={{ value: '时间 (ms)', angle: -90, position: 'insideLeft' }} />
76 <Tooltip formatter={(val) => typeof val === 'number' ? `${val.toFixed(2)} ms` : val} />
77 <Legend />
78 <Line type="monotone" dataKey="elapsed_time" stroke="#8884d8" name="响应时间 (ms)" />
79 </LineChart>
80 </ResponsiveContainer>
81 </div>
82
83 {/* CPU时间图表 */}
84 <div style={{ marginBottom: '30px' }}>
85 <h3>CPU 使用时间</h3>
86 <ResponsiveContainer width="100%" height={300}>
87 <LineChart data={data} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
88 <CartesianGrid strokeDasharray="3 3" />
89 <XAxis
90 dataKey="record_time_ts"
91 type="number"
92 domain={['dataMin', 'dataMax']}
93 tickFormatter={ts => new Date(ts).toLocaleTimeString()}
94 />
95 <YAxis domain={[0, 'auto']} label={{ value: '时间 (ms)', angle: -90, position: 'insideLeft' }} />
96 <Tooltip formatter={(val) => typeof val === 'number' ? `${val.toFixed(2)} ms` : val} />
97 <Legend />
98 <Line type="monotone" dataKey="cpu_user" stroke="#82ca9d" name="CPU 用户时间 (ms)" />
99 <Line type="monotone" dataKey="cpu_system" stroke="#ffc658" name="CPU 系统时间 (ms)" />
100 </LineChart>
101 </ResponsiveContainer>
102 </div>
103
104 {/* 内存图表 */}
105 <div style={{ marginBottom: '30px' }}>
106 <h3>内存使用</h3>
107 <ResponsiveContainer width="100%" height={300}>
108 <LineChart data={data} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
109 <CartesianGrid strokeDasharray="3 3" />
110 <XAxis
111 dataKey="record_time_ts"
112 type="number"
113 domain={['dataMin', 'dataMax']}
114 tickFormatter={ts => new Date(ts).toLocaleTimeString()}
115 />
116 <YAxis domain={[0, 'auto']} label={{ value: '内存 (MB)', angle: -90, position: 'insideLeft' }} />
117 <Tooltip formatter={(val) => typeof val === 'number' ? `${val.toFixed(2)} MB` : val} />
118 <Legend />
119 <Line type="monotone" dataKey="memory_rss" stroke="#ff7300" name="内存 RSS" />
120 </LineChart>
121 </ResponsiveContainer>
122 </div>
TRM-coding85e5c322025-06-18 19:49:21 +0800123 </section>
124 );
125}
126
127export default PerformanceLogs;