UNPKG

bc-code-intelligence-mcp

Version:

BC Code Intelligence MCP Server - Complete Specialist Bundle with AI-driven expert consultation, seamless handoffs, and context-preserving workflows

253 lines 9.9 kB
/** * Performance Monitor for BCKB System * * Tracks performance metrics, identifies bottlenecks, and provides * optimization recommendations for production deployments. */ export class PerformanceMonitor { enableDetailedTracking; enableSlowQueryLogging; slowQueryThresholdMs; metrics = []; errorCount = 0; totalRequests = 0; startTime = Date.now(); maxMetrics = 1000; // Keep last 1000 metrics constructor(enableDetailedTracking = true, enableSlowQueryLogging = true, slowQueryThresholdMs = 1000) { this.enableDetailedTracking = enableDetailedTracking; this.enableSlowQueryLogging = enableSlowQueryLogging; this.slowQueryThresholdMs = slowQueryThresholdMs; console.log(`📊 Performance monitor initialized (detailed: ${enableDetailedTracking})`); } /** * Track a performance metric */ trackOperation(operation, durationMs, metadata) { if (!this.enableDetailedTracking) return; const metric = { operation, duration_ms: durationMs, timestamp: Date.now(), metadata }; this.metrics.push(metric); // Log slow operations if (this.enableSlowQueryLogging && durationMs > this.slowQueryThresholdMs) { console.warn(`🐌 Slow operation detected: ${operation} took ${durationMs}ms`, metadata); } // Keep only recent metrics to prevent memory growth if (this.metrics.length > this.maxMetrics) { this.metrics.shift(); } this.totalRequests++; } /** * Time and track an async operation */ async timeOperation(operation, fn, metadata) { const startTime = Date.now(); try { const result = await fn(); const duration = Date.now() - startTime; this.trackOperation(operation, duration, { ...metadata, success: true }); return result; } catch (error) { const duration = Date.now() - startTime; this.errorCount++; this.trackOperation(operation, duration, { ...metadata, success: false, error: error instanceof Error ? error.message : String(error) }); throw error; } } /** * Create a timer for manual tracking */ createTimer(operation, metadata) { const startTime = Date.now(); return { stop: (additionalMetadata) => { const duration = Date.now() - startTime; this.trackOperation(operation, duration, { ...metadata, ...additionalMetadata }); return duration; } }; } /** * Get performance summary for a specific operation */ getOperationSummary(operation) { const operationMetrics = this.metrics.filter(m => m.operation === operation); if (operationMetrics.length === 0) return null; const durations = operationMetrics.map(m => m.duration_ms).sort((a, b) => a - b); const total = durations.reduce((sum, d) => sum + d, 0); return { total_operations: operationMetrics.length, average_duration_ms: total / operationMetrics.length, p95_duration_ms: durations[Math.floor(durations.length * 0.95)] || 0, p99_duration_ms: durations[Math.floor(durations.length * 0.99)] || 0, operations_per_second: this.calculateOpsPerSecond(operationMetrics), slowest_operations: [...operationMetrics] .sort((a, b) => (b.duration_ms || 0) - (a.duration_ms || 0)) .slice(0, 5), fastest_operations: [...operationMetrics] .sort((a, b) => (a.duration_ms || 0) - (b.duration_ms || 0)) .slice(0, 5) }; } /** * Get overall system performance summary */ getOverallSummary() { if (this.metrics.length === 0) { return { total_operations: 0, average_duration_ms: 0, p95_duration_ms: 0, p99_duration_ms: 0, operations_per_second: 0, slowest_operations: [], fastest_operations: [] }; } const durations = this.metrics.map(m => m.duration_ms).sort((a, b) => a - b); const total = durations.reduce((sum, d) => sum + d, 0); return { total_operations: this.metrics.length, average_duration_ms: total / this.metrics.length, p95_duration_ms: durations[Math.floor(durations.length * 0.95)] || 0, p99_duration_ms: durations[Math.floor(durations.length * 0.99)] || 0, operations_per_second: this.calculateOpsPerSecond(this.metrics), slowest_operations: [...this.metrics] .sort((a, b) => (b.duration_ms || 0) - (a.duration_ms || 0)) .slice(0, 10), fastest_operations: [...this.metrics] .sort((a, b) => (a.duration_ms || 0) - (b.duration_ms || 0)) .slice(0, 10) }; } /** * Get system health metrics */ getSystemHealth() { const memoryUsage = process.memoryUsage(); const uptime = (Date.now() - this.startTime) / 1000; // Calculate average response time from recent metrics const recentMetrics = this.metrics.slice(-100); // Last 100 operations const avgResponseTime = recentMetrics.length > 0 ? recentMetrics.reduce((sum, m) => sum + m.duration_ms, 0) / recentMetrics.length : 0; return { memory_usage_mb: memoryUsage.heapUsed / 1024 / 1024, cache_hit_rate: 0, // This would be provided by cache manager active_layers: 0, // This would be provided by layer service total_topics: 0, // This would be provided by layer service average_response_time_ms: avgResponseTime, error_rate: this.totalRequests > 0 ? (this.errorCount / this.totalRequests * 100) : 0, uptime_seconds: uptime }; } /** * Get optimization recommendations based on performance data */ getOptimizationRecommendations() { const recommendations = []; const summary = this.getOverallSummary(); const health = this.getSystemHealth(); // High latency detection if (summary.average_duration_ms > 500) { recommendations.push({ type: 'latency', message: 'Average response time is high. Consider optimizing slow operations or increasing cache size.', priority: 'high', impact: 'Significant performance improvement' }); } // Memory usage recommendations if (health.memory_usage_mb > 500) { recommendations.push({ type: 'memory', message: 'High memory usage detected. Consider reducing cache size or optimizing memory-intensive operations.', priority: 'medium', impact: 'Reduced memory pressure' }); } // Error rate recommendations if (health.error_rate > 5) { recommendations.push({ type: 'reliability', message: 'High error rate detected. Review error logs and improve error handling.', priority: 'high', impact: 'Improved system stability' }); } // Performance variance recommendations if (summary.p99_duration_ms > summary.average_duration_ms * 5) { recommendations.push({ type: 'consistency', message: 'High performance variance detected. Some operations are much slower than others.', priority: 'medium', impact: 'More consistent response times' }); } return recommendations; } /** * Get operation breakdown by frequency and performance */ getOperationBreakdown() { const breakdown = {}; for (const metric of this.metrics) { if (!breakdown[metric.operation]) { breakdown[metric.operation] = { count: 0, total_duration: 0 }; } breakdown[metric.operation].count++; breakdown[metric.operation].total_duration += metric.duration_ms; } // Convert to final format with averages const result = {}; for (const [operation, data] of Object.entries(breakdown)) { result[operation] = { count: data.count, avg_duration: data.total_duration / data.count, total_time: data.total_duration }; } return result; } /** * Clear all metrics (useful for testing or memory management) */ clearMetrics() { this.metrics = []; this.errorCount = 0; this.totalRequests = 0; console.log('📊 Performance metrics cleared'); } /** * Export metrics for external analysis */ exportMetrics() { return { metrics: [...this.metrics], // Copy to prevent external modification summary: this.getOverallSummary(), system_health: this.getSystemHealth(), operation_breakdown: this.getOperationBreakdown() }; } // Private helper methods calculateOpsPerSecond(metrics) { if (metrics.length < 2) return 0; const timeSpan = metrics[metrics.length - 1].timestamp - metrics[0].timestamp; if (timeSpan === 0) return 0; return (metrics.length / timeSpan) * 1000; // Convert to operations per second } } //# sourceMappingURL=performance-monitor.js.map