/** * Monitoring routes for system health and metrics */ import { Hono } from 'hono'; import type { IServiceContainer } from '@stock-bot/handlers'; import { MonitoringService } from '../services/monitoring.service'; export function createMonitoringRoutes(container: IServiceContainer) { const monitoring = new Hono(); const monitoringService = new MonitoringService(container); /** * Get overall system health */ monitoring.get('/', async c => { try { const health = await monitoringService.getSystemHealth(); // Set appropriate status code based on health const statusCode = health.status === 'healthy' ? 200 : health.status === 'degraded' ? 503 : 500; return c.json(health, statusCode); } catch (error) { return c.json( { status: 'error', message: 'Failed to retrieve system health', error: error instanceof Error ? error.message : 'Unknown error', }, 500 ); } }); /** * Get cache/Dragonfly statistics */ monitoring.get('/cache', async c => { try { const stats = await monitoringService.getCacheStats(); return c.json(stats); } catch (error) { return c.json( { error: 'Failed to retrieve cache statistics', message: error instanceof Error ? error.message : 'Unknown error', }, 500 ); } }); /** * Get queue statistics */ monitoring.get('/queues', async c => { try { const stats = await monitoringService.getQueueStats(); return c.json({ queues: stats }); } catch (error) { return c.json( { error: 'Failed to retrieve queue statistics', message: error instanceof Error ? error.message : 'Unknown error', }, 500 ); } }); /** * Get specific queue statistics */ monitoring.get('/queues/:name', async c => { try { const queueName = c.req.param('name'); const stats = await monitoringService.getQueueStats(); const queueStats = stats.find(q => q.name === queueName); if (!queueStats) { return c.json( { error: 'Queue not found', message: `Queue '${queueName}' does not exist`, }, 404 ); } return c.json(queueStats); } catch (error) { return c.json( { error: 'Failed to retrieve queue statistics', message: error instanceof Error ? error.message : 'Unknown error', }, 500 ); } }); /** * Get database statistics */ monitoring.get('/databases', async c => { try { const stats = await monitoringService.getDatabaseStats(); return c.json({ databases: stats }); } catch (error) { return c.json( { error: 'Failed to retrieve database statistics', message: error instanceof Error ? error.message : 'Unknown error', }, 500 ); } }); /** * Get specific database statistics */ monitoring.get('/databases/:type', async c => { try { const dbType = c.req.param('type') as 'postgres' | 'mongodb' | 'questdb'; const stats = await monitoringService.getDatabaseStats(); const dbStats = stats.find(db => db.type === dbType); if (!dbStats) { return c.json( { error: 'Database not found', message: `Database type '${dbType}' not found or not enabled`, }, 404 ); } return c.json(dbStats); } catch (error) { return c.json( { error: 'Failed to retrieve database statistics', message: error instanceof Error ? error.message : 'Unknown error', }, 500 ); } }); /** * Get service metrics */ monitoring.get('/metrics', async c => { try { const metrics = await monitoringService.getServiceMetrics(); return c.json(metrics); } catch (error) { return c.json( { error: 'Failed to retrieve service metrics', message: error instanceof Error ? error.message : 'Unknown error', }, 500 ); } }); /** * Get detailed cache info (Redis INFO command output) */ monitoring.get('/cache/info', async c => { try { if (!container.cache) { return c.json( { error: 'Cache not available', message: 'Cache service is not enabled', }, 503 ); } const info = await container.cache.info(); const stats = await monitoringService.getCacheStats(); return c.json({ parsed: stats, raw: info, }); } catch (error) { return c.json( { error: 'Failed to retrieve cache info', message: error instanceof Error ? error.message : 'Unknown error', }, 500 ); } }); /** * Health check endpoint for monitoring */ monitoring.get('/ping', c => { return c.json({ status: 'ok', timestamp: new Date().toISOString(), service: 'monitoring', }); }); /** * Get service status for all microservices */ monitoring.get('/services', async c => { try { const services = await monitoringService.getServiceStatus(); return c.json({ services }); } catch (error) { return c.json( { error: 'Failed to retrieve service status', message: error instanceof Error ? error.message : 'Unknown error', }, 500 ); } }); /** * Get proxy statistics */ monitoring.get('/proxies', async c => { try { const stats = await monitoringService.getProxyStats(); return c.json(stats || { enabled: false }); } catch (error) { return c.json( { error: 'Failed to retrieve proxy statistics', message: error instanceof Error ? error.message : 'Unknown error', }, 500 ); } }); /** * Get comprehensive system overview */ monitoring.get('/overview', async c => { try { const overview = await monitoringService.getSystemOverview(); return c.json(overview); } catch (error) { return c.json( { error: 'Failed to retrieve system overview', message: error instanceof Error ? error.message : 'Unknown error', }, 500 ); } }); /** * Test direct BullMQ queue access */ monitoring.get('/test/queue/:name', async c => { const queueName = c.req.param('name'); const { Queue } = await import('bullmq'); const connection = { host: 'localhost', port: 6379, db: 0, // All queues in DB 0 }; const queue = new Queue(queueName, { connection }); try { const counts = await queue.getJobCounts(); await queue.close(); return c.json({ queueName, counts, }); } catch (error: any) { await queue.close(); return c.json( { queueName, error: error.message, }, 500 ); } }); return monitoring; }