import express from 'express';
import { logger } from '../utils/logger.js';
import searchService from '../services/searchService.js';
const router = express.Router();
// Basic health check
router.get('/', (req, res) => {
res.json({
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
memory: process.memoryUsage(),
version: process.version
});
});
// Detailed health check
router.get('/detailed', async (req, res) => {
try {
const healthData = {
status: 'healthy',
timestamp: new Date().toISOString(),
system: {
uptime: process.uptime(),
memory: process.memoryUsage(),
cpu: process.cpuUsage(),
version: process.version,
platform: process.platform,
arch: process.arch
},
services: {}
};
// Check search service status
try {
// Try to initialize browser if not already initialized
if (!searchService.browser) {
await searchService.initBrowser();
healthData.services.searchService = {
status: 'healthy',
browser: 'initialized'
};
} else {
healthData.services.searchService = {
status: 'healthy',
browser: 'running'
};
}
} catch (error) {
healthData.services.searchService = {
status: 'unhealthy',
error: error.message
};
healthData.status = 'degraded';
}
// Check network connectivity
try {
const startTime = Date.now();
const response = await fetch('https://httpbin.org/get', {
method: 'GET',
timeout: 5000
});
const responseTime = Date.now() - startTime;
healthData.services.network = {
status: 'healthy',
responseTime: `${responseTime}ms`,
statusCode: response.status
};
} catch (error) {
healthData.services.network = {
status: 'unhealthy',
error: error.message
};
healthData.status = 'degraded';
}
// Check disk space (if available)
try {
const fs = await import('fs/promises');
const stats = await fs.stat('.');
healthData.services.disk = {
status: 'healthy',
available: true
};
} catch (error) {
healthData.services.disk = {
status: 'unknown',
error: error.message
};
}
const statusCode = healthData.status === 'healthy' ? 200 : 503;
res.status(statusCode).json(healthData);
} catch (error) {
logger.error('Detailed health check error:', error);
res.status(500).json({
status: 'unhealthy',
error: 'Health check failed',
message: error.message,
timestamp: new Date().toISOString()
});
}
});
// Readiness check
router.get('/ready', async (req, res) => {
try {
// Check if key services are ready
const checks = {
searchService: false,
network: false
};
// Check search service
try {
if (!searchService.browser) {
await searchService.initBrowser();
}
checks.searchService = true;
} catch (error) {
logger.warn('Search service not ready:', error.message);
}
// Check network connectivity
try {
const response = await fetch('https://httpbin.org/get', {
method: 'GET',
timeout: 3000
});
checks.network = response.ok;
} catch (error) {
logger.warn('Network not ready:', error.message);
}
const isReady = Object.values(checks).every(check => check === true);
const statusCode = isReady ? 200 : 503;
res.status(statusCode).json({
ready: isReady,
checks,
timestamp: new Date().toISOString()
});
} catch (error) {
logger.error('Readiness check error:', error);
res.status(500).json({
ready: false,
error: 'Readiness check failed',
message: error.message,
timestamp: new Date().toISOString()
});
}
});
// Liveness check
router.get('/live', (req, res) => {
res.json({
alive: true,
timestamp: new Date().toISOString(),
pid: process.pid
});
});
// Metrics endpoint
router.get('/metrics', (req, res) => {
const metrics = {
timestamp: new Date().toISOString(),
process: {
uptime: process.uptime(),
memory: process.memoryUsage(),
cpu: process.cpuUsage()
},
system: {
platform: process.platform,
arch: process.arch,
version: process.version
}
};
res.json(metrics);
});
export { router as healthRouter };