Spaces:
Running
Running
import { Hono } from 'hono'; | |
import { config } from '../config'; | |
const healthApp = new Hono(); | |
interface HealthStatus { | |
status: 'healthy' | 'degraded' | 'unhealthy'; | |
timestamp: string; | |
uptime: number; | |
services: { | |
backend: { | |
status: 'up' | 'down'; | |
responseTime?: number; | |
error?: string; | |
}; | |
cache: { | |
status: 'up' | 'down'; | |
size?: number; | |
}; | |
}; | |
} | |
// Basic health check | |
healthApp.get('/', async (c) => { | |
const startTime = Date.now(); | |
const health: HealthStatus = { | |
status: 'healthy', | |
timestamp: new Date().toISOString(), | |
uptime: process.uptime(), | |
services: { | |
backend: { status: 'down' }, | |
cache: { status: 'up' }, | |
}, | |
}; | |
// Check backend health | |
try { | |
const backendStart = Date.now(); | |
const response = await fetch(`${config.backendUrl}/health`, { | |
signal: AbortSignal.timeout(5000), // 5 second timeout | |
}); | |
if (response.ok) { | |
health.services.backend = { | |
status: 'up', | |
responseTime: Date.now() - backendStart, | |
}; | |
} else { | |
health.services.backend = { | |
status: 'down', | |
error: `HTTP ${response.status}`, | |
}; | |
health.status = 'degraded'; | |
} | |
} catch (error) { | |
health.services.backend = { | |
status: 'down', | |
error: error instanceof Error ? error.message : 'Unknown error', | |
}; | |
health.status = 'degraded'; | |
} | |
// Overall health determination | |
const allServicesUp = Object.values(health.services).every(s => s.status === 'up'); | |
if (!allServicesUp) { | |
health.status = 'degraded'; | |
} | |
// Return appropriate status code | |
const statusCode = health.status === 'healthy' ? 200 : 503; | |
return c.json(health, statusCode); | |
}); | |
// Liveness probe (for k8s) | |
healthApp.get('/live', (c) => { | |
return c.json({ status: 'alive', timestamp: new Date().toISOString() }); | |
}); | |
// Readiness probe (for k8s) | |
healthApp.get('/ready', async (c) => { | |
try { | |
// Quick check if backend is reachable | |
const response = await fetch(`${config.backendUrl}/health`, { | |
signal: AbortSignal.timeout(2000), | |
}); | |
if (response.ok) { | |
return c.json({ ready: true }); | |
} | |
return c.json({ ready: false, reason: 'Backend not ready' }, 503); | |
} catch (error) { | |
return c.json({ | |
ready: false, | |
reason: error instanceof Error ? error.message : 'Unknown error' | |
}, 503); | |
} | |
}); | |
export { healthApp }; |