+
${escapeHtml(server.totalRequests)}
Total Requests
+
${escapeHtml(server.avgMs)}ms
Avg Response
+
${escapeHtml(health ? health.uptimeHuman : Math.round(server.uptime / 60) + 'm')}
Uptime
+
${server.slowQueries.length}
Slow (>100ms)
+ ${renderVersionCard(health)}
+
`;
+ }
+
async function render(app) {
// The selector stays outside perfContent's existing five-second DOM
// rebuild, preserving keyboard focus and an open native select menu.
- app.innerHTML = ' Performance Dashboard
' +
+ app.innerHTML = '
Performance Dashboard
' +
'
' +
- '
WebSocket clients
' +
'Loading history…
Loading...
';
const selector = document.getElementById('wsHistoryRange');
@@ -346,18 +360,11 @@ function renderVersionCard(health) {
const historyEl = document.getElementById('wsHistoryContent');
if (historyEl) historyEl.innerHTML = renderWSClientHistory(wsHistory, health && health.websocket ? health.websocket.clients : null, range, false) ||
'
History is temporarily unavailable. Retrying on the next refresh.
';
+ const overviewEl = document.getElementById('perfOverview');
+ if (overviewEl) overviewEl.innerHTML = renderPerfOverview(server, health);
let html = '';
- // Server overview
- html += `
-
${escapeHtml(server.totalRequests)}
Total Requests
-
${escapeHtml(server.avgMs)}ms
Avg Response
-
${escapeHtml(health ? health.uptimeHuman : Math.round(server.uptime / 60) + 'm')}
Uptime
-
${server.slowQueries.length}
Slow (>100ms)
- ${renderVersionCard(health)}
-
`;
-
// System health (memory, event loop / go runtime, WS)
if (health) {
const isGo = health.engine === 'go';
diff --git a/public/style.css b/public/style.css
index e55500588..ad52dd119 100644
--- a/public/style.css
+++ b/public/style.css
@@ -3714,12 +3714,15 @@ button.region-pill-active:hover { opacity: 0.85; color: var(--text-on-accent); }
margin-right: 2px; user-select: none; white-space: nowrap; flex-shrink: 0;
}
.analytics-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 8px 0; }
-.analytics-time-window-select {
+/* The one time-window / metric