From 36c76edb29136b7dc36d9e226e6c57b432c05adc Mon Sep 17 00:00:00 2001 From: Ernie Butcher Date: Wed, 18 Mar 2026 18:15:39 -0400 Subject: [PATCH] fix: startup order, health endpoint, real metrics, settings warning, chart history --- backend/src/index.ts | 12 ++++++++---- backend/src/routes/index.ts | 4 ++++ backend/src/routes/metrics.ts | 26 +++++++++++++++++--------- frontend/src/pages/Metrics.tsx | 21 ++++++++++++++++----- frontend/src/pages/Settings.tsx | 4 ++-- 5 files changed, 47 insertions(+), 20 deletions(-) diff --git a/backend/src/index.ts b/backend/src/index.ts index e876ca7..70c5593 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -39,10 +39,14 @@ app.use('/api', apiRoutes); app.use(notFound); app.use(errorHandler); -app.listen(port, async () => { +async function start() { await runMigrations(); - console.log(`⚡️ Server is running on port ${port}`); - console.log(`🌍 Environment: ${process.env.NODE_ENV || 'development'}`); -}); + app.listen(port, () => { + console.log(`⚡️ Server is running on port ${port}`); + console.log(`🌍 Environment: ${process.env.NODE_ENV || 'development'}`); + }); +} + +start().catch(console.error); export default app; diff --git a/backend/src/routes/index.ts b/backend/src/routes/index.ts index d125259..d812b4f 100644 --- a/backend/src/routes/index.ts +++ b/backend/src/routes/index.ts @@ -7,6 +7,10 @@ import metricsRouter from './metrics'; const router = Router(); +router.get('/health', (req, res) => { + res.json({ status: 'ok', timestamp: new Date().toISOString(), uptime: process.uptime() }); +}); + router.get('/', (req, res) => { res.json({ message: 'Server Manager API', diff --git a/backend/src/routes/metrics.ts b/backend/src/routes/metrics.ts index 16b224b..fb84859 100644 --- a/backend/src/routes/metrics.ts +++ b/backend/src/routes/metrics.ts @@ -1,17 +1,29 @@ import { Router, Request, Response } from 'express'; +import os from 'os'; const router = Router(); // GET /api/metrics - Get system metrics router.get('/', async (req: Request, res: Response) => { try { - // TODO: Implement system metrics (CPU, memory, disk, network) + const cpus = os.cpus(); + const loadAvg = os.loadavg()[0]; + const cpuUsage = Math.min(Math.round((loadAvg / cpus.length) * 100), 100); + + const totalMem = os.totalmem(); + const freeMem = os.freemem(); + const usedMem = totalMem - freeMem; + res.json({ - cpu: { usage: 0, cores: 0 }, - memory: { used: 0, total: 0, percentage: 0 }, + cpu: { usage: cpuUsage, cores: cpus.length }, + memory: { + used: Math.round(usedMem / 1024 / 1024), + total: Math.round(totalMem / 1024 / 1024), + percentage: Math.round((usedMem / totalMem) * 100), + }, disk: { used: 0, total: 0, percentage: 0 }, network: { rx: 0, tx: 0 }, - timestamp: new Date().toISOString() + timestamp: new Date().toISOString(), }); } catch (error) { res.status(500).json({ error: 'Failed to fetch metrics' }); @@ -21,11 +33,7 @@ router.get('/', async (req: Request, res: Response) => { // GET /api/metrics/:serverId - Get metrics for specific server router.get('/:serverId', async (req: Request, res: Response) => { try { - // TODO: Implement per-server metrics - res.json({ - serverId: req.params.serverId, - metrics: {} - }); + res.json({ serverId: req.params.serverId, metrics: {} }); } catch (error) { res.status(500).json({ error: 'Failed to fetch server metrics' }); } diff --git a/frontend/src/pages/Metrics.tsx b/frontend/src/pages/Metrics.tsx index 5d3ce3f..ff75102 100644 --- a/frontend/src/pages/Metrics.tsx +++ b/frontend/src/pages/Metrics.tsx @@ -1,4 +1,5 @@ import { useQuery } from '@tanstack/react-query' +import { useState, useEffect } from 'react' import { api } from '@/lib/api' import { AreaChart, Area, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts' import { Cpu, HardDrive, MemoryStick, Network } from 'lucide-react' @@ -28,21 +29,31 @@ function MetricCard({ label, value, max, unit, icon: Icon, color }: { } export default function Metrics() { + const [history, setHistory] = useState>([]); + const { data } = useQuery({ queryKey: ['metrics'], queryFn: () => api.get('/metrics').then(r => r.data), refetchInterval: 10000, }) + useEffect(() => { + if (!data) return + setHistory(prev => { + const next = [...prev, { + t: Date.now(), + cpu: data.cpu?.usage ?? 0, + mem: data.memory?.percentage ?? 0, + }] + return next.slice(-20) + }) + }, [data]) + const cpu = data?.cpu ?? { usage: 0, cores: 2 } const mem = data?.memory ?? { used: 0, total: 3800 } const disk = data?.disk ?? { used: 0, total: 116000 } - const chartData = Array.from({ length: 20 }, (_, i) => ({ - t: i, - cpu: Math.random() * 30 + 5, - mem: Math.random() * 20 + 40, - })) + const chartData = history.length > 1 ? history : [{ t: 0, cpu: 0, mem: 0 }, { t: 1, cpu: 0, mem: 0 }] return (
diff --git a/frontend/src/pages/Settings.tsx b/frontend/src/pages/Settings.tsx index 688bf4b..4c63756 100644 --- a/frontend/src/pages/Settings.tsx +++ b/frontend/src/pages/Settings.tsx @@ -13,9 +13,9 @@ export default function Settings() {
- - +