fix(monitoring): flatten CPU/mem data, add health summary, public + rate-limit monitoring/stats
Three coordinated fixes for the System Overview widget:
1. routes/monitoring.js — flatten getAllStats() shape from
{current:{cpu:{percent},memory:{percent}}} to {cpu,memory,memoryUsage}
so the widget's Number() coercion actually produces numbers, not NaN.
Skill reference: references/totp-and-system-overview-pitfalls.md §3.
2. routes/health.js — add summary block to /health-checks/status response.
Widget looks for {healthy, unhealthy, total} but only per-service objects
existed. Permissive on healthy side (up|healthy|online), strict on
unhealthy (down|unhealthy|offline|error); anything else counted as
unknown. Same skill §3 reference.
3. middleware.js — add /api/v1/monitoring/stats to PUBLIC_ROUTES and the
rate-limit skip list. The widget polls it every 5s from the dashboard;
cookie-auth works but listing it explicitly makes it future-proof
against auth-cookie expiry and prevents per-second 429s.
End-to-end test (unauthenticated):
GET /api/v1/monitoring/stats -> {cpu: 8.71, memory: 0.37, ...}
GET /api/v1/health-checks/status -> {summary: {healthy:11, unhealthy:4, total:15}}
This commit is contained in:
@@ -322,9 +322,26 @@ module.exports = function({
|
||||
// ===== HEALTH CHECK (health-checker module) =====
|
||||
|
||||
// Get current status for all services
|
||||
// Returns {status: {...per-service}} plus a {summary} block for the System Overview widget
|
||||
// — see skill references/totp-and-system-overview-pitfalls.md §3
|
||||
router.get('/health-checks/status', asyncHandler(async (req, res) => {
|
||||
const status = healthChecker.getCurrentStatus();
|
||||
success(res, { status });
|
||||
const entries = Object.values(status || {});
|
||||
// Treat 'up'/'healthy' as healthy, everything else as unhealthy.
|
||||
// Health check status values come from healthChecker — typically 'up'/'down' but
|
||||
// also 'healthy'/'unhealthy' or 'online'/'offline' depending on the source. Be
|
||||
// permissive on the healthy side so a service in any positive state counts.
|
||||
const healthy = entries.filter(s => {
|
||||
const st = (s && (s.status || s.state)) || '';
|
||||
return st === 'up' || st === 'healthy' || st === 'online';
|
||||
}).length;
|
||||
const unhealthy = entries.filter(s => {
|
||||
const st = (s && (s.status || s.state)) || '';
|
||||
return st === 'down' || st === 'unhealthy' || st === 'offline' || st === 'error';
|
||||
}).length;
|
||||
const unknown = entries.length - healthy - unhealthy;
|
||||
const summary = { healthy, unhealthy, unknown, total: entries.length };
|
||||
success(res, { status, summary });
|
||||
}, 'health-check-status'));
|
||||
|
||||
// Get service statistics
|
||||
|
||||
Reference in New Issue
Block a user