Skip to main content
Glama

CodeCompass MCP

monitor.js12.3 kB
#!/usr/bin/env node // CodeCompass MCP Monitoring Dashboard // Based on patterns from OpenRouter MCP repository import { monitoring } from '../build/utils/monitoring.js'; import { log } from '../build/utils/logger.js'; // Colors for terminal output const colors = { reset: '\x1b[0m', bright: '\x1b[1m', dim: '\x1b[2m', red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m', magenta: '\x1b[35m', cyan: '\x1b[36m', white: '\x1b[37m', gray: '\x1b[90m', }; // Status symbols const symbols = { healthy: '✅', degraded: '⚠️', unhealthy: '❌', info: 'ℹ️', warning: '⚠️', error: '❌', success: '✅', }; // Format bytes to human readable function formatBytes(bytes) { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } // Format duration to human readable function formatDuration(ms) { const seconds = Math.floor(ms / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`; if (hours > 0) return `${hours}h ${minutes % 60}m ${seconds % 60}s`; if (minutes > 0) return `${minutes}m ${seconds % 60}s`; return `${seconds}s`; } // Format percentage with color function formatPercentage(value, threshold = 80) { const color = value >= threshold ? colors.red : value >= threshold * 0.8 ? colors.yellow : colors.green; return `${color}${value}%${colors.reset}`; } // Format status with color and symbol function formatStatus(status) { const color = status === 'healthy' ? colors.green : status === 'degraded' ? colors.yellow : colors.red; const symbol = symbols[status]; return `${color}${symbol} ${status.toUpperCase()}${colors.reset}`; } // Clear screen function clearScreen() { process.stdout.write('\x1b[2J\x1b[0f'); } // Display header function displayHeader() { console.log(colors.bright + colors.blue + '╔══════════════════════════════════════════════════════════════════════════════╗' + colors.reset); console.log(colors.bright + colors.blue + '║ CodeCompass MCP Monitor ║' + colors.reset); console.log(colors.bright + colors.blue + '╚══════════════════════════════════════════════════════════════════════════════╝' + colors.reset); console.log(); } // Display system metrics function displaySystemMetrics(metrics) { console.log(colors.bright + colors.cyan + '📊 System Metrics' + colors.reset); console.log(colors.gray + '─'.repeat(80) + colors.reset); console.log(`${colors.bright}Uptime:${colors.reset} ${formatDuration(metrics.uptime)}`); console.log(`${colors.bright}Memory:${colors.reset} ${formatBytes(metrics.memory.heapUsed)} / ${formatBytes(metrics.memory.heapTotal)} (${formatPercentage(Math.round((metrics.memory.heapUsed / metrics.memory.heapTotal) * 100), 80)})`); console.log(`${colors.bright}RSS:${colors.reset} ${formatBytes(metrics.memory.rss)}`); console.log(`${colors.bright}External:${colors.reset} ${formatBytes(metrics.memory.external)}`); console.log(); } // Display request metrics function displayRequestMetrics(metrics) { console.log(colors.bright + colors.cyan + '📈 Request Metrics' + colors.reset); console.log(colors.gray + '─'.repeat(80) + colors.reset); console.log(`${colors.bright}Total Requests:${colors.reset} ${metrics.requestCount.toLocaleString()}`); console.log(`${colors.bright}Error Count:${colors.reset} ${metrics.errorCount.toLocaleString()}`); console.log(`${colors.bright}Error Rate:${colors.reset} ${formatPercentage(metrics.requestCount > 0 ? Math.round((metrics.errorCount / metrics.requestCount) * 100) : 0, 10)}`); console.log(`${colors.bright}Average Response Time:${colors.reset} ${metrics.responseTime.average}ms`); console.log(`${colors.bright}Min Response Time:${colors.reset} ${metrics.responseTime.min}ms`); console.log(`${colors.bright}Max Response Time:${colors.reset} ${metrics.responseTime.max}ms`); console.log(`${colors.bright}95th Percentile:${colors.reset} ${metrics.responseTime.percentile95}ms`); console.log(); } // Display health status function displayHealthStatus(health) { console.log(colors.bright + colors.cyan + '🏥 Health Status' + colors.reset); console.log(colors.gray + '─'.repeat(80) + colors.reset); console.log(`${colors.bright}Overall Status:${colors.reset} ${formatStatus(health.status)}`); console.log(); Object.entries(health.checks).forEach(([check, data]) => { console.log(`${colors.bright}${check}:${colors.reset} ${formatStatus(data.status)}`); if (check === 'memory') { console.log(` Usage: ${formatPercentage(data.usage)} (limit: ${data.limit}%)`); } else if (check === 'errorRate') { console.log(` Rate: ${formatPercentage(data.rate)} (limit: ${data.limit}%)`); } else if (check === 'recentErrors') { console.log(` Count: ${data.count} (limit: ${data.limit})`); } else if (check === 'responseTime') { console.log(` Average: ${data.average}ms (limit: ${data.limit}ms)`); } }); console.log(); } // Display tool usage function displayToolUsage(toolStats) { console.log(colors.bright + colors.cyan + '🔧 Tool Usage' + colors.reset); console.log(colors.gray + '─'.repeat(80) + colors.reset); if (toolStats.length === 0) { console.log(colors.gray + 'No tool usage data available' + colors.reset); console.log(); return; } toolStats.slice(0, 10).forEach(tool => { const errorColor = tool.errorRate > 10 ? colors.red : tool.errorRate > 5 ? colors.yellow : colors.green; console.log(`${colors.bright}${tool.tool}:${colors.reset} ${tool.count} calls (${tool.percentage}%)`); console.log(` Avg Response: ${tool.averageResponseTime}ms | Error Rate: ${errorColor}${tool.errorRate}%${colors.reset}`); }); console.log(); } // Display recent requests function displayRecentRequests(requests) { console.log(colors.bright + colors.cyan + '📋 Recent Requests (Last 10)' + colors.reset); console.log(colors.gray + '─'.repeat(80) + colors.reset); if (requests.length === 0) { console.log(colors.gray + 'No recent requests' + colors.reset); console.log(); return; } requests.slice(0, 10).forEach(req => { const timestamp = new Date(req.timestamp).toLocaleTimeString(); const status = req.success ? colors.green + '✓' : colors.red + '✗'; const duration = req.duration < 1000 ? colors.green : req.duration < 5000 ? colors.yellow : colors.red; console.log(`${timestamp} ${status} ${colors.bright}${req.tool}${colors.reset} ${duration}${req.duration}ms${colors.reset}`); if (!req.success && req.error) { console.log(` ${colors.red}Error: ${req.error}${colors.reset}`); } }); console.log(); } // Display performance insights function displayInsights(insights) { console.log(colors.bright + colors.cyan + '💡 Performance Insights' + colors.reset); console.log(colors.gray + '─'.repeat(80) + colors.reset); if (insights.slowestTools.length > 0) { console.log(`${colors.bright}Slowest Tools:${colors.reset}`); insights.slowestTools.slice(0, 3).forEach(tool => { console.log(` ${tool.tool}: ${tool.avgTime}ms`); }); console.log(); } if (insights.mostErrorProneTools.length > 0) { console.log(`${colors.bright}Most Error-Prone Tools:${colors.reset}`); insights.mostErrorProneTools.slice(0, 3).forEach(tool => { console.log(` ${tool.tool}: ${tool.errorRate}%`); }); console.log(); } if (insights.peakUsageHours.length > 0) { console.log(`${colors.bright}Peak Usage Hours:${colors.reset}`); insights.peakUsageHours.slice(0, 3).forEach(hour => { console.log(` ${hour.hour}:00 - ${hour.requestCount} requests`); }); console.log(); } if (insights.recommendations.length > 0) { console.log(`${colors.bright}Recommendations:${colors.reset}`); insights.recommendations.forEach(rec => { console.log(` ${symbols.info} ${rec}`); }); } console.log(); } // Display logs function displayLogs() { console.log(colors.bright + colors.cyan + '📜 Recent Logs' + colors.reset); console.log(colors.gray + '─'.repeat(80) + colors.reset); const logBuffer = log.getLogBuffer(); const recentLogs = logBuffer.slice(-10); if (recentLogs.length === 0) { console.log(colors.gray + 'No logs available' + colors.reset); console.log(); return; } recentLogs.forEach(logEntry => { const timestamp = new Date(logEntry.timestamp).toLocaleTimeString(); const level = logEntry.level === 0 ? colors.gray + 'DEBUG' : logEntry.level === 1 ? colors.blue + 'INFO' : logEntry.level === 2 ? colors.yellow + 'WARN' : colors.red + 'ERROR'; console.log(`${timestamp} ${level}${colors.reset} ${logEntry.message}`); if (logEntry.error) { console.log(` ${colors.red}${logEntry.error.message}${colors.reset}`); } }); console.log(); } // Main dashboard function function displayDashboard() { clearScreen(); displayHeader(); try { const metrics = monitoring.getMetrics(); const health = monitoring.getHealthStatus(); const toolStats = monitoring.getToolUsageStats(); const recentRequests = monitoring.getRecentRequests(10); const insights = monitoring.getPerformanceInsights(); displaySystemMetrics(metrics); displayRequestMetrics(metrics); displayHealthStatus(health); displayToolUsage(toolStats); displayRecentRequests(recentRequests); displayInsights(insights); displayLogs(); console.log(colors.gray + `Last updated: ${new Date().toLocaleString()}` + colors.reset); console.log(colors.gray + 'Press Ctrl+C to exit' + colors.reset); } catch (error) { console.error(colors.red + 'Error displaying dashboard:', error.message + colors.reset); } } // Command line interface function main() { const args = process.argv.slice(2); if (args.includes('--help') || args.includes('-h')) { console.log('CodeCompass MCP Monitor'); console.log(''); console.log('Usage: node monitor.js [options]'); console.log(''); console.log('Options:'); console.log(' --watch, -w Watch mode (refresh every 5 seconds)'); console.log(' --export, -e Export metrics to JSON'); console.log(' --reset, -r Reset metrics'); console.log(' --help, -h Show this help message'); return; } if (args.includes('--export') || args.includes('-e')) { console.log('Exporting metrics...'); console.log(monitoring.exportMetrics()); return; } if (args.includes('--reset') || args.includes('-r')) { console.log('Resetting metrics...'); monitoring.resetMetrics(); console.log('Metrics reset successfully'); return; } if (args.includes('--watch') || args.includes('-w')) { console.log('Starting monitor in watch mode...'); displayDashboard(); // Refresh every 5 seconds const interval = setInterval(() => { displayDashboard(); }, 5000); // Handle Ctrl+C process.on('SIGINT', () => { clearInterval(interval); console.log(colors.bright + colors.green + '\n\nMonitor stopped' + colors.reset); process.exit(0); }); } else { // Single run displayDashboard(); } } // Handle uncaught exceptions process.on('uncaughtException', (error) => { console.error(colors.red + 'Uncaught Exception:', error.message + colors.reset); process.exit(1); }); process.on('unhandledRejection', (reason, promise) => { console.error(colors.red + 'Unhandled Rejection at:', promise, 'reason:', reason + colors.reset); process.exit(1); }); // Run the monitor main();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TheAlchemist6/codecompass-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server