UNPKG

devflow-ai

Version:

Enterprise-grade AI agent orchestration with swarm management UI dashboard

655 lines (574 loc) 20.5 kB
/** * Memory Monitor and Optimization System * * Provides real-time monitoring, analysis, and optimization * recommendations for the Hive Mind memory subsystem. */ import { EventEmitter } from 'events'; import { performance } from 'perf_hooks'; import { Memory } from './Memory.js'; import { DatabaseManager } from './DatabaseManager.js'; interface MemoryAlert { level: 'info' | 'warning' | 'critical'; type: string; message: string; value: number; threshold: number; timestamp: Date; recommendations: string[]; } interface OptimizationSuggestion { type: 'cache' | 'database' | 'pool' | 'compression' | 'cleanup'; priority: 'low' | 'medium' | 'high' | 'critical'; title: string; description: string; estimatedImpact: string; implementation: string; effort: 'minimal' | 'moderate' | 'significant'; } interface MemoryHealthReport { overall: { score: number; status: 'excellent' | 'good' | 'fair' | 'poor' | 'critical'; summary: string; }; metrics: { cacheHitRate: number; avgQueryTime: number; memoryUtilization: number; compressionRatio: number; poolEfficiency: number; }; alerts: MemoryAlert[]; suggestions: OptimizationSuggestion[]; trends: { performance: 'improving' | 'stable' | 'degrading'; memoryUsage: 'increasing' | 'stable' | 'decreasing'; cacheEfficiency: 'improving' | 'stable' | 'degrading'; }; } export class MemoryMonitor extends EventEmitter { private memory: Memory; private db: DatabaseManager; private isActive = false; private monitoringTimers: NodeJS.Timeout[] = []; private historicalData: Map<string, number[]> = new Map(); private alertThresholds = { cacheHitRate: { warning: 50, critical: 30 }, avgQueryTime: { warning: 100, critical: 500 }, memoryUtilization: { warning: 80, critical: 95 }, poolReuseRate: { warning: 30, critical: 10 }, }; private alerts: MemoryAlert[] = []; private maxHistorySize = 1000; constructor(memory: Memory, db: DatabaseManager) { super(); this.memory = memory; this.db = db; } /** * Start memory monitoring */ async start(): Promise<void> { if (this.isActive) return; this.isActive = true; // Real-time monitoring (every 10 seconds) const realtimeTimer = setInterval(() => { this.collectMetrics(); }, 10000); // Health analysis (every minute) const healthTimer = setInterval(() => { this.analyzeHealth(); }, 60000); // Trend analysis (every 5 minutes) const trendTimer = setInterval(() => { this.analyzeTrends(); }, 300000); // Optimization suggestions (every 15 minutes) const optimizationTimer = setInterval(() => { this.generateOptimizationSuggestions(); }, 900000); // Alert cleanup (every hour) const cleanupTimer = setInterval(() => { this.cleanupOldAlerts(); }, 3600000); this.monitoringTimers.push( realtimeTimer, healthTimer, trendTimer, optimizationTimer, cleanupTimer, ); // Initial baseline collection await this.establishBaseline(); this.emit('monitoring:started'); } /** * Stop memory monitoring */ stop(): void { this.isActive = false; this.monitoringTimers.forEach((timer) => clearInterval(timer)); this.monitoringTimers.length = 0; this.emit('monitoring:stopped'); } /** * Collect real-time metrics */ private async collectMetrics(): Promise<void> { if (!this.isActive) return; try { const startTime = performance.now(); // Get memory analytics const memoryAnalytics = this.memory.getAdvancedAnalytics(); const dbAnalytics = this.db.getDatabaseAnalytics(); // Extract key metrics const metrics = { cacheHitRate: memoryAnalytics.cache.hitRate || 0, avgQueryTime: dbAnalytics.performance.query_execution?.avg || 0, memoryUtilization: memoryAnalytics.cache.utilizationPercent || 0, poolEfficiency: this.calculatePoolEfficiency(memoryAnalytics.pools), dbFragmentation: dbAnalytics.fragmentation || 0, activeConnections: 1, // Simplified for now timestamp: Date.now(), }; // Store historical data this.storeHistoricalData(metrics); // Check for alerts this.checkAlerts(metrics); const duration = performance.now() - startTime; this.emit('metrics:collected', { metrics, duration }); } catch (error) { this.emit('error', error); } } /** * Establish performance baseline */ private async establishBaseline(): Promise<void> { const samples = []; for (let i = 0; i < 10; i++) { await this.collectMetrics(); await new Promise((resolve) => setTimeout(resolve, 1000)); } this.emit('baseline:established', { samples: samples.length }); } /** * Store historical performance data */ private storeHistoricalData(metrics: any): void { for (const [key, value] of Object.entries(metrics)) { if (typeof value === 'number') { if (!this.historicalData.has(key)) { this.historicalData.set(key, []); } const history = this.historicalData.get(key)!; history.push(value); // Limit history size if (history.length > this.maxHistorySize) { history.shift(); } } } } /** * Check metrics against alert thresholds */ private checkAlerts(metrics: any): void { const newAlerts: MemoryAlert[] = []; // Cache hit rate alerts const cacheHitRate = metrics.cacheHitRate; if (cacheHitRate < this.alertThresholds.cacheHitRate.critical) { newAlerts.push({ level: 'critical', type: 'cache_performance', message: `Cache hit rate critically low: ${cacheHitRate.toFixed(1)}%`, value: cacheHitRate, threshold: this.alertThresholds.cacheHitRate.critical, timestamp: new Date(), recommendations: [ 'Increase cache size immediately', 'Review access patterns', 'Consider cache warming strategies', ], }); } else if (cacheHitRate < this.alertThresholds.cacheHitRate.warning) { newAlerts.push({ level: 'warning', type: 'cache_performance', message: `Cache hit rate below optimal: ${cacheHitRate.toFixed(1)}%`, value: cacheHitRate, threshold: this.alertThresholds.cacheHitRate.warning, timestamp: new Date(), recommendations: [ 'Monitor cache patterns', 'Consider increasing cache size', 'Review cache eviction policy', ], }); } // Query performance alerts const avgQueryTime = metrics.avgQueryTime; if (avgQueryTime > this.alertThresholds.avgQueryTime.critical) { newAlerts.push({ level: 'critical', type: 'query_performance', message: `Query performance critically slow: ${avgQueryTime.toFixed(1)}ms`, value: avgQueryTime, threshold: this.alertThresholds.avgQueryTime.critical, timestamp: new Date(), recommendations: [ 'Immediate database optimization required', 'Review query plans and indexes', 'Consider query result caching', ], }); } else if (avgQueryTime > this.alertThresholds.avgQueryTime.warning) { newAlerts.push({ level: 'warning', type: 'query_performance', message: `Query performance degraded: ${avgQueryTime.toFixed(1)}ms`, value: avgQueryTime, threshold: this.alertThresholds.avgQueryTime.warning, timestamp: new Date(), recommendations: [ 'Monitor query performance trends', 'Consider database maintenance', 'Review recent schema changes', ], }); } // Memory utilization alerts const memoryUtilization = metrics.memoryUtilization; if (memoryUtilization > this.alertThresholds.memoryUtilization.critical) { newAlerts.push({ level: 'critical', type: 'memory_utilization', message: `Memory utilization critical: ${memoryUtilization.toFixed(1)}%`, value: memoryUtilization, threshold: this.alertThresholds.memoryUtilization.critical, timestamp: new Date(), recommendations: [ 'Immediate memory cleanup required', 'Increase memory limits', 'Enable aggressive garbage collection', ], }); } else if (memoryUtilization > this.alertThresholds.memoryUtilization.warning) { newAlerts.push({ level: 'warning', type: 'memory_utilization', message: `Memory utilization high: ${memoryUtilization.toFixed(1)}%`, value: memoryUtilization, threshold: this.alertThresholds.memoryUtilization.warning, timestamp: new Date(), recommendations: [ 'Monitor memory usage trends', 'Consider memory optimization', 'Review cache sizes', ], }); } // Add new alerts and emit events if (newAlerts.length > 0) { this.alerts.push(...newAlerts); newAlerts.forEach((alert) => { this.emit('alert', alert); }); } } /** * Analyze overall system health */ private async analyzeHealth(): Promise<void> { const memoryHealth = await this.memory.healthCheck(); const dbHealth = await this.db.healthCheck(); const analytics = this.memory.getAdvancedAnalytics(); const healthReport: MemoryHealthReport = { overall: { score: this.calculateOverallScore(memoryHealth, dbHealth, analytics), status: 'good', summary: '', }, metrics: { cacheHitRate: analytics.cache.hitRate || 0, avgQueryTime: this.getAverageFromHistory('avgQueryTime'), memoryUtilization: analytics.cache.utilizationPercent || 0, compressionRatio: 0.7, // Simplified poolEfficiency: this.calculatePoolEfficiency(analytics.pools), }, alerts: this.getActiveAlerts(), suggestions: this.generateHealthSuggestions(analytics), trends: this.calculateTrends(), }; // Determine status if (healthReport.overall.score >= 90) { healthReport.overall.status = 'excellent'; } else if (healthReport.overall.score >= 75) { healthReport.overall.status = 'good'; } else if (healthReport.overall.score >= 60) { healthReport.overall.status = 'fair'; } else if (healthReport.overall.score >= 40) { healthReport.overall.status = 'poor'; } else { healthReport.overall.status = 'critical'; } // Generate summary healthReport.overall.summary = this.generateHealthSummary(healthReport); this.emit('health:analyzed', healthReport); } /** * Generate optimization suggestions */ private generateOptimizationSuggestions(): void { const analytics = this.memory.getAdvancedAnalytics(); const suggestions: OptimizationSuggestion[] = []; // Cache optimization suggestions if ((analytics.cache.hitRate || 0) < 70) { suggestions.push({ type: 'cache', priority: 'high', title: 'Optimize Cache Configuration', description: 'Cache hit rate is below optimal threshold', estimatedImpact: 'Reduce database queries by 20-40%', implementation: 'Increase cache size and adjust eviction policy', effort: 'minimal', }); } // Database optimization suggestions const avgQueryTime = this.getAverageFromHistory('avgQueryTime'); if (avgQueryTime > 50) { suggestions.push({ type: 'database', priority: 'medium', title: 'Database Performance Tuning', description: 'Query execution times are above optimal range', estimatedImpact: 'Improve query performance by 30-50%', implementation: 'Add indexes, optimize queries, run ANALYZE', effort: 'moderate', }); } // Pool optimization suggestions const poolEfficiency = this.calculatePoolEfficiency(analytics.pools); if (poolEfficiency < 50) { suggestions.push({ type: 'pool', priority: 'low', title: 'Object Pool Optimization', description: 'Object pools have low reuse rates', estimatedImpact: 'Reduce garbage collection pressure', implementation: 'Increase pool sizes and improve object lifecycle', effort: 'minimal', }); } this.emit('suggestions:generated', suggestions); } /** * Calculate pool efficiency */ private calculatePoolEfficiency(pools: any): number { if (!pools) return 0; const efficiencies = Object.values(pools).map((pool: any) => pool.reuseRate || 0); return efficiencies.length > 0 ? efficiencies.reduce((a, b) => a + b, 0) / efficiencies.length : 0; } /** * Get average value from historical data */ private getAverageFromHistory(metric: string): number { const history = this.historicalData.get(metric); if (!history || history.length === 0) return 0; return history.reduce((a, b) => a + b, 0) / history.length; } /** * Calculate overall health score */ private calculateOverallScore(memoryHealth: any, dbHealth: any, analytics: any): number { let score = 100; // Cache performance impact (30%) const cacheHitRate = analytics.cache.hitRate || 0; score -= Math.max(0, (70 - cacheHitRate) * 0.3); // Query performance impact (25%) const avgQueryTime = this.getAverageFromHistory('avgQueryTime'); if (avgQueryTime > 50) { score -= Math.min(25, (avgQueryTime - 50) * 0.5); } // Memory utilization impact (20%) const memoryUtil = analytics.cache.utilizationPercent || 0; if (memoryUtil > 80) { score -= (memoryUtil - 80) * 0.5; } // Active alerts impact (15%) const criticalAlerts = this.alerts.filter((a) => a.level === 'critical').length; const warningAlerts = this.alerts.filter((a) => a.level === 'warning').length; score -= criticalAlerts * 10 + warningAlerts * 5; // Pool efficiency impact (10%) const poolEff = this.calculatePoolEfficiency(analytics.pools); score -= Math.max(0, (50 - poolEff) * 0.2); return Math.max(0, Math.min(100, score)); } /** * Get active alerts (within last hour) */ private getActiveAlerts(): MemoryAlert[] { const oneHourAgo = Date.now() - 3600000; return this.alerts.filter((alert) => alert.timestamp.getTime() > oneHourAgo); } /** * Generate health-based suggestions */ private generateHealthSuggestions(analytics: any): OptimizationSuggestion[] { const suggestions: OptimizationSuggestion[] = []; // Add specific suggestions based on current state if ((analytics.cache.utilizationPercent || 0) > 90) { suggestions.push({ type: 'cache', priority: 'critical', title: 'Immediate Cache Memory Relief', description: 'Cache memory utilization is critically high', estimatedImpact: 'Prevent system instability', implementation: 'Increase cache memory limit or enable aggressive cleanup', effort: 'minimal', }); } return suggestions; } /** * Calculate performance trends */ private calculateTrends(): any { const trends = { performance: 'stable' as 'improving' | 'stable' | 'degrading', memoryUsage: 'stable' as 'increasing' | 'stable' | 'decreasing', cacheEfficiency: 'stable' as 'improving' | 'stable' | 'degrading', }; // Analyze query time trend const queryTimes = this.historicalData.get('avgQueryTime') || []; if (queryTimes.length >= 10) { const recent = queryTimes.slice(-5); const older = queryTimes.slice(-10, -5); const recentAvg = recent.reduce((a, b) => a + b, 0) / recent.length; const olderAvg = older.reduce((a, b) => a + b, 0) / older.length; if (recentAvg < olderAvg * 0.9) { trends.performance = 'improving'; } else if (recentAvg > olderAvg * 1.1) { trends.performance = 'degrading'; } } // Analyze memory usage trend const memoryUsage = this.historicalData.get('memoryUtilization') || []; if (memoryUsage.length >= 10) { const recent = memoryUsage.slice(-5); const older = memoryUsage.slice(-10, -5); const recentAvg = recent.reduce((a, b) => a + b, 0) / recent.length; const olderAvg = older.reduce((a, b) => a + b, 0) / older.length; if (recentAvg > olderAvg * 1.05) { trends.memoryUsage = 'increasing'; } else if (recentAvg < olderAvg * 0.95) { trends.memoryUsage = 'decreasing'; } } // Analyze cache efficiency trend const cacheHitRates = this.historicalData.get('cacheHitRate') || []; if (cacheHitRates.length >= 10) { const recent = cacheHitRates.slice(-5); const older = cacheHitRates.slice(-10, -5); const recentAvg = recent.reduce((a, b) => a + b, 0) / recent.length; const olderAvg = older.reduce((a, b) => a + b, 0) / older.length; if (recentAvg > olderAvg * 1.05) { trends.cacheEfficiency = 'improving'; } else if (recentAvg < olderAvg * 0.95) { trends.cacheEfficiency = 'degrading'; } } return trends; } /** * Analyze trends over time */ private analyzeTrends(): void { const trends = this.calculateTrends(); this.emit('trends:analyzed', trends); } /** * Generate health summary */ private generateHealthSummary(report: MemoryHealthReport): string { const { overall, metrics, alerts } = report; if (overall.status === 'excellent') { return 'All memory systems are operating at peak efficiency with optimal performance metrics.'; } else if (overall.status === 'good') { return 'Memory systems are performing well with minor optimization opportunities.'; } else if (overall.status === 'fair') { return `Memory performance is acceptable but ${alerts.length} issue(s) need attention.`; } else if (overall.status === 'poor') { return `Memory systems require optimization. Cache hit rate: ${metrics.cacheHitRate.toFixed(1)}%, Avg query time: ${metrics.avgQueryTime.toFixed(1)}ms.`; } else { return `Critical memory issues detected. Immediate intervention required. ${alerts.filter((a) => a.level === 'critical').length} critical alert(s) active.`; } } /** * Clean up old alerts */ private cleanupOldAlerts(): void { const cutoff = Date.now() - 86400000; // 24 hours const initialCount = this.alerts.length; this.alerts = this.alerts.filter((alert) => alert.timestamp.getTime() > cutoff); const cleaned = initialCount - this.alerts.length; if (cleaned > 0) { this.emit('alerts:cleaned', { cleaned }); } } /** * Get current monitoring status */ getStatus() { return { isActive: this.isActive, alertCount: this.alerts.length, criticalAlerts: this.alerts.filter((a) => a.level === 'critical').length, warningAlerts: this.alerts.filter((a) => a.level === 'warning').length, historicalDataPoints: Array.from(this.historicalData.entries()).map(([key, values]) => ({ metric: key, samples: values.length, })), }; } /** * Get detailed memory report */ async generateDetailedReport(): Promise<MemoryHealthReport> { const memoryHealth = await this.memory.healthCheck(); const dbHealth = await this.db.healthCheck(); const analytics = this.memory.getAdvancedAnalytics(); return { overall: { score: this.calculateOverallScore(memoryHealth, dbHealth, analytics), status: 'good', summary: '', }, metrics: { cacheHitRate: analytics.cache.hitRate || 0, avgQueryTime: this.getAverageFromHistory('avgQueryTime'), memoryUtilization: analytics.cache.utilizationPercent || 0, compressionRatio: 0.7, poolEfficiency: this.calculatePoolEfficiency(analytics.pools), }, alerts: this.getActiveAlerts(), suggestions: this.generateHealthSuggestions(analytics), trends: this.calculateTrends(), }; } /** * Export monitoring data for analysis */ exportData() { return { historicalData: Object.fromEntries(this.historicalData), alerts: this.alerts, thresholds: this.alertThresholds, status: this.getStatus(), }; } }