/** * Container Health & Metrics Endpoint * Add this to your main application containers for self-reporting */ const express = require('express'); const os = require('os'); const fs = require('fs'); const { exec } = require('child_process'); const { promisify } = require('util'); const execAsync = promisify(exec); /** * Health & Metrics endpoint implementation * Add this to your Express app in each container */ const createHealthEndpoint = (app) => { app.get('/health/metrics', async (req, res) => { try { const containerName = process.env.CONTAINER_NAME || 'unknown-container'; const memUsage = process.memoryUsage(); const cpuUsage = process.cpuUsage(); // Get system load average const loadAvg = os.loadavg(); // Get network connections (if available) let networkConnections = 'N/A'; try { const { stdout } = await execAsync('netstat -an | grep ESTABLISHED | wc -l'); networkConnections = parseInt(stdout.trim()); } catch (e) { // Network info not available } // Get disk usage for common paths let diskUsage = {}; try { const paths = ['/tmp', '/var/log', '/app']; for (const path of paths) { if (fs.existsSync(path)) { const stats = fs.statSync(path); diskUsage[path] = `${Math.round(stats.size / 1024 / 1024)}MB`; } } } catch (e) { diskUsage = { error: 'Disk info unavailable' }; } // Calculate CPU percentage (approximate) const cpuPercent = ((cpuUsage.user + cpuUsage.system) / 1000000 / process.uptime() * 100).toFixed(1); const metrics = { container: containerName, timestamp: new Date().toISOString(), uptime: Math.round(process.uptime()), health: 'healthy', version: process.env.APP_VERSION || '1.0.0', // Memory metrics memory: { usage: `${Math.round(memUsage.heapUsed / 1024 / 1024)}MB / ${Math.round(memUsage.heapTotal / 1024 / 1024)}MB`, percentage: `${Math.round((memUsage.heapUsed / memUsage.heapTotal) * 100)}%`, rss: `${Math.round(memUsage.rss / 1024 / 1024)}MB`, external: `${Math.round(memUsage.external / 1024 / 1024)}MB` }, // CPU metrics cpu: `${cpuPercent}%`, // System metrics system: { platform: os.platform(), arch: os.arch(), nodeVersion: process.version, loadAverage: loadAvg[0].toFixed(2) }, // Network metrics network: { connections: networkConnections, requests_handled: global.requestCounter || 0 }, // Disk metrics disk: diskUsage, // Additional app-specific metrics application: { environment: process.env.NODE_ENV || 'development', pid: process.pid, ppid: process.ppid } }; res.json({ success: true, data: metrics, source: 'internal_health_endpoint' }); } catch (error) { res.status(500).json({ success: false, error: 'Failed to collect metrics', message: error.message, container: process.env.CONTAINER_NAME || 'unknown-container' }); } }); // Simple health check endpoint app.get('/health', (req, res) => { res.json({ status: 'healthy', timestamp: new Date().toISOString(), uptime: process.uptime(), container: process.env.CONTAINER_NAME || 'unknown-container' }); }); }; /** * Middleware to count requests (for metrics) */ const requestCounter = (req, res, next) => { global.requestCounter = (global.requestCounter || 0) + 1; next(); }; /** * Enhanced logging for metrics */ const logMetrics = () => { const memUsage = process.memoryUsage(); const metrics = { timestamp: new Date().toISOString(), container: process.env.CONTAINER_NAME || 'unknown-container', memory_mb: Math.round(memUsage.heapUsed / 1024 / 1024), uptime_seconds: Math.round(process.uptime()), requests_handled: global.requestCounter || 0 }; console.log(`METRICS: ${JSON.stringify(metrics)}`); }; // Example usage in your main app: /* const app = express(); // Add request counter middleware app.use(requestCounter); // Add health endpoints createHealthEndpoint(app); // Log metrics every 30 seconds setInterval(logMetrics, 30000); // Your other routes... app.listen(3000, () => { console.log('Server started with health endpoints'); }); */ module.exports = { createHealthEndpoint, requestCounter, logMetrics };