sanket3280/code-execution
0
1/**2 * System Monitoring Utilities3 * Provides monitoring and metrics collection4 */5 6const logger = require('./logger');7const { isConnected } = require('./database');8 9/**10 * Monitor system health periodically11 */12class HealthMonitor {13 constructor(intervalMs = 60000) { // Default: 1 minute14 this.intervalMs = intervalMs;15 this.interval = null;16 this.metrics = {17 uptime: 0,18 memory: {},19 database: {},20 lastCheck: null,21 };22 }23 24 /**25 * Start monitoring26 */27 start() {28 if (this.interval) {29 logger.warn('Health monitor already running');30 return;31 }32 33 logger.info(`Starting health monitor (interval: ${this.intervalMs}ms)`);34 35 // Run initial check36 this.check();37 38 // Schedule periodic checks39 this.interval = setInterval(() => {40 this.check();41 }, this.intervalMs);42 }43 44 /**45 * Stop monitoring46 */47 stop() {48 if (this.interval) {49 clearInterval(this.interval);50 this.interval = null;51 logger.info('Health monitor stopped');52 }53 }54 55 /**56 * Perform health check57 */58 check() {59 try {60 // Update metrics61 this.metrics.uptime = process.uptime();62 this.metrics.lastCheck = new Date().toISOString();63 64 // Memory metrics65 const memory = process.memoryUsage();66 this.metrics.memory = {67 heapUsed: Math.round(memory.heapUsed / 1024 / 1024),68 heapTotal: Math.round(memory.heapTotal / 1024 / 1024),69 rss: Math.round(memory.rss / 1024 / 1024),70 external: Math.round(memory.external / 1024 / 1024),71 percentage: Math.round((memory.heapUsed / memory.heapTotal) * 100),72 };73 74 // Database metrics75 this.metrics.database = {76 connected: isConnected(),77 };78 79 // Log warnings for high resource usage80 if (this.metrics.memory.percentage > 85) {81 logger.warn(`High memory usage: ${this.metrics.memory.percentage}%`, {82 heapUsed: `${this.metrics.memory.heapUsed}MB`,83 heapTotal: `${this.metrics.memory.heapTotal}MB`,84 });85 }86 87 if (!this.metrics.database.connected) {88 logger.error('Database connection lost');89 }90 91 // Log periodic health status (only in development)92 if (process.env.NODE_ENV === 'development') {93 logger.debug('Health check', this.metrics);94 }95 } catch (error) {96 logger.error('Health check failed', error);97 }98 }99 100 /**101 * Get current metrics102 */103 getMetrics() {104 return { ...this.metrics };105 }106}107 108/**109 * Request metrics tracker110 */111class RequestMetrics {112 constructor() {113 this.metrics = {114 total: 0,115 success: 0,116 errors: 0,117 byMethod: {},118 byStatus: {},119 averageResponseTime: 0,120 totalResponseTime: 0,121 };122 }123 124 /**125 * Record a request126 */127 record(method, statusCode, responseTime) {128 this.metrics.total++;129 this.metrics.totalResponseTime += responseTime;130 this.metrics.averageResponseTime = Math.round(131 this.metrics.totalResponseTime / this.metrics.total132 );133 134 // Count by method135 this.metrics.byMethod[method] = (this.metrics.byMethod[method] || 0) + 1;136 137 // Count by status138 const statusGroup = `${Math.floor(statusCode / 100)}xx`;139 this.metrics.byStatus[statusGroup] = (this.metrics.byStatus[statusGroup] || 0) + 1;140 141 // Count success/errors142 if (statusCode >= 200 && statusCode < 400) {143 this.metrics.success++;144 } else {145 this.metrics.errors++;146 }147 }148 149 /**150 * Get metrics151 */152 getMetrics() {153 return {154 ...this.metrics,155 successRate: this.metrics.total > 0156 ? Math.round((this.metrics.success / this.metrics.total) * 100)157 : 0,158 errorRate: this.metrics.total > 0159 ? Math.round((this.metrics.errors / this.metrics.total) * 100)160 : 0,161 };162 }163 164 /**165 * Reset metrics166 */167 reset() {168 this.metrics = {169 total: 0,170 success: 0,171 errors: 0,172 byMethod: {},173 byStatus: {},174 averageResponseTime: 0,175 totalResponseTime: 0,176 };177 }178}179 180/**181 * Request tracking middleware182 */183const requestTracker = (requestMetrics) => {184 return (req, res, next) => {185 const startTime = Date.now();186 187 // Capture response188 res.on('finish', () => {189 const responseTime = Date.now() - startTime;190 requestMetrics.record(req.method, res.statusCode, responseTime);191 192 // Log slow requests193 if (responseTime > 1000) {194 logger.warn('Slow request detected', {195 method: req.method,196 path: req.path,197 responseTime: `${responseTime}ms`,198 statusCode: res.statusCode,199 });200 }201 });202 203 next();204 };205};206 207// Export singleton instances208const healthMonitor = new HealthMonitor();209const requestMetrics = new RequestMetrics();210 211module.exports = {212 HealthMonitor,213 RequestMetrics,214 healthMonitor,215 requestMetrics,216 requestTracker,217};218 