fix: DevTools 仪表盘平均请求延迟显示进程运行时间而非实际请求耗时

- performance.js: 新增 recordLatency/getAverageLatency, 用 HTTP 请求环缓冲区替换 pidusage elapsed
- index.js: 新增 Express 中间件追踪每个请求耗时
- index.html: 移除前端 elapsed-based fallback 计算

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 16:37:25 +08:00
parent 189f7b999b
commit 271a3a048d
4 changed files with 35 additions and 17 deletions
+1 -8
View File
@@ -1286,15 +1286,8 @@ async function updatePerformanceDashboard(perfData) {
const cpuLevel = avgCpu > 80 ? 'cpu-high' : avgCpu > 50 ? 'cpu-mid' : 'cpu-low';
const memLevel = totalMem > 1024 ? 'mem-high' : totalMem > 512 ? 'mem-mid' : 'mem-low';
// 计算平均延迟 (基于活跃连接和服务数估算,或使用 perf 数据中的 elapsed)
// 计算平均延迟 (从 API 获取实际请求耗时)
let avgLatency = '—';
let totalElapsed = 0, elapsedCount = 0;
for (const [, p] of entries) {
if (p.elapsed && p.elapsed > 0) { totalElapsed += p.elapsed; elapsedCount++; }
}
if (elapsedCount > 0) {
avgLatency = Math.round(totalElapsed / elapsedCount) + 'ms';
}
// 获取趋势数据 (从性能仪表盘 API)
let trendCpu = '→', trendMem = '→';
+9
View File
@@ -33,6 +33,15 @@ const __dirname = path.dirname(__filename);
const app = express();
app.use(express.json());
// 请求延时追踪 — 记录每个 HTTP 请求的实际耗时
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
performanceMonitor.recordLatency(Date.now() - start);
});
next();
});
// 静态文件 - Web控制台
app.use(express.static(path.join(__dirname, '../public')));
+21 -9
View File
@@ -13,11 +13,30 @@ class PerformanceMonitor {
this.history = new Map();
this.interval = null;
// Ring buffer for actual HTTP request latencies (ms)
this.latencyBuffer = [];
this.maxLatencySamples = 500;
for (const id of Object.keys(SERVICES)) {
this.history.set(id, []);
}
}
/** Record an HTTP request duration (ms). Called by middleware. */
recordLatency(durationMs) {
this.latencyBuffer.push(durationMs);
if (this.latencyBuffer.length > this.maxLatencySamples) {
this.latencyBuffer.splice(0, this.latencyBuffer.length - this.maxLatencySamples);
}
}
/** Get average request latency from recent samples. Returns null if no data. */
getAverageLatency() {
if (this.latencyBuffer.length === 0) return null;
const sum = this.latencyBuffer.reduce((a, b) => a + b, 0);
return Math.round(sum / this.latencyBuffer.length);
}
/**
* 开始定期采样 (每3秒)
*/
@@ -123,15 +142,8 @@ class PerformanceMonitor {
const avgCpu = entries.length > 0 ? Math.round(totalCpu / entries.length * 10) / 10 : 0;
const totalMemRounded = Math.round(totalMem * 100) / 100;
// 计算平均延迟 (基于各服务进程的 elapsed 时间)
let avgLatencyMs = null;
let totalElapsed = 0, elapsedCount = 0;
for (const [, p] of entries) {
if (p.elapsed && p.elapsed > 0) { totalElapsed += p.elapsed; elapsedCount++; }
}
if (elapsedCount > 0) {
avgLatencyMs = Math.round(totalElapsed / elapsedCount);
}
// 计算平均请求延迟 (基于实际 HTTP 请求耗时,非进程 uptime)
const avgLatencyMs = this.getAverageLatency();
// 获取最近历史用于趋势判断
const recentHistory = this.getAllHistory();
+4
View File
@@ -37,3 +37,7 @@
- [Phase 2 - 人格与交互深化](2026-05-23-phase2-personality-interaction.md) — 情感状态机 + 主动消息决策增强 + 离线自主思考 (16 文件)
- [Phase 3 - 插件与工具系统](2026-05-23-phase3-plugin-tool-system.md) — Plugin SDK + Plugin Manager + 13 内置插件 + 工具分级 (40 文件)
- [Phase 4 - 多平台接入](2026-05-23-phase4-multi-platform.md) — 统一消息模型 + QQ/Telegram/Webhook 适配器 + 身份权限系统 (18 文件)
## 2026-05-24
- [Phase 6 - 多模型配置系统 + 视觉集成](2026-05-24-phase6-model-config-vision.md) — ModelSelector 路由 + LLM 调用日志 + Vision/OCR 集成 + Bug 修复 (9 文件)