diff --git a/nginx.conf b/nginx.conf index 5f52f8b..fb34d21 100644 --- a/nginx.conf +++ b/nginx.conf @@ -18,33 +18,6 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } - # Kuma assets and websocket — must come before /monitor/ to match first - location /monitor/assets/ { - proxy_pass http://10.10.10.105:3002/assets/; - proxy_set_header Host $host; - } - location /monitor/socket.io/ { - proxy_pass http://10.10.10.105:3002/socket.io/; - proxy_set_header Host $host; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_http_version 1.1; - } - location /monitor/ { - proxy_pass http://10.10.10.105:3002/; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_http_version 1.1; - # Rewrite Kuma's absolute /assets/ and /socket.io/ refs to /monitor/* - proxy_set_header Accept-Encoding ""; - sub_filter '"/assets/' '"/monitor/assets/'; - sub_filter '"/socket.io/' '"/monitor/socket.io/'; - sub_filter_once off; - } - location /deploy/ { proxy_pass http://10.10.10.105:9000/; proxy_set_header Host $host; diff --git a/src/pages/AdminMonitor.tsx b/src/pages/AdminMonitor.tsx index 60f8e9c..a4b6d67 100644 --- a/src/pages/AdminMonitor.tsx +++ b/src/pages/AdminMonitor.tsx @@ -12,6 +12,12 @@ interface AppStatus { checkedAt: string } +interface HealthStatus { + name: string + up: boolean + ms: number | null +} + interface DeployEntry { repo: string host: string @@ -23,9 +29,10 @@ interface DeployEntry { } export function AdminMonitor({ user }: { user: User }) { - const [tab, setTab] = useState<'updates' | 'kuma' | 'deploys'>('updates') + const [tab, setTab] = useState<'updates' | 'uptime' | 'deploys'>('updates') const [statuses, setStatuses] = useState([]) const [deploys, setDeploys] = useState([]) + const [health, setHealth] = useState([]) const [loading, setLoading] = useState(false) const [deploying, setDeploying] = useState>(new Set()) @@ -39,6 +46,16 @@ export function AdminMonitor({ user }: { user: User }) { } } + async function fetchHealth() { + setLoading(true) + try { + const res = await fetch('/deploy/health-status', { credentials: 'include' }) + if (res.ok) setHealth(await res.json()) + } finally { + setLoading(false) + } + } + async function fetchDeploys() { setLoading(true) try { @@ -65,6 +82,11 @@ export function AdminMonitor({ user }: { user: User }) { useEffect(() => { if (tab === 'updates') fetchStatus() if (tab === 'deploys') fetchDeploys() + if (tab === 'uptime') { + fetchHealth() + const id = setInterval(fetchHealth, 30_000) + return () => clearInterval(id) + } }, [tab]) const updatesAvailable = statuses.filter(s => s.updateAvailable).length @@ -77,7 +99,7 @@ export function AdminMonitor({ user }: { user: User }) { display: 'flex', borderBottom: '1px solid var(--surface-2)', background: 'var(--navy)', flexShrink: 0, }}> - {(['updates', 'kuma', 'deploys'] as const).map(t => ( + {(['updates', 'uptime', 'deploys'] as const).map(t => ( ))} @@ -168,8 +190,46 @@ export function AdminMonitor({ user }: { user: User }) { )} - {tab === 'kuma' && ( -