UNPKG

snow-flow

Version:

Snow-Flow v3.2.0: Complete ServiceNow Enterprise Suite with 180+ MCP Tools. ATF Testing, Knowledge Management, Service Catalog, Change Management with CAB scheduling, Virtual Agent chatbots with NLU, Performance Analytics KPIs, Flow Designer automation, A

1,086 lines (1,063 loc) 45.1 kB
"use strict"; /** * 🚀 PERFORMANCE FIX: Enhanced Monitoring System * Advanced real-time monitoring with predictive analytics, alerting, and dashboards * * Addresses beta testing feedback on performance monitoring gaps */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.EnhancedMonitoringSystem = void 0; const events_1 = require("events"); const logger_1 = require("../utils/logger"); const ws_1 = __importDefault(require("ws")); const http_1 = __importDefault(require("http")); class EnhancedMonitoringSystem extends events_1.EventEmitter { constructor(performanceTracker, memory, config) { super(); this.activeAlerts = new Map(); this.metricHistory = new Map(); this.connectedClients = new Set(); this.performanceTracker = performanceTracker; this.memory = memory; this.logger = new logger_1.Logger('EnhancedMonitoringSystem'); this.config = { realTimeEnabled: true, predictiveAnalyticsEnabled: true, alertingEnabled: true, dashboardEnabled: true, websocketPort: 8090, alertThresholds: { cpuUsage: 80, memoryUsage: 85, diskUsage: 90, responseTime: 5000, errorRate: 10, cacheHitRate: 50, queueDepth: 100 }, retentionPeriods: { realTimeMetrics: 3600000, // 1 hour hourlyAggregates: 2592000000, // 30 days dailyAggregates: 7776000000, // 90 days weeklyAggregates: 31536000000 // 1 year }, ...config }; this.systemHealth = this.initializeSystemHealth(); this.logger.info('🚀 Enhanced Monitoring System initialized', { realTimeEnabled: this.config.realTimeEnabled, predictiveAnalyticsEnabled: this.config.predictiveAnalyticsEnabled, alertingEnabled: this.config.alertingEnabled, dashboardEnabled: this.config.dashboardEnabled }); } /** * Start the enhanced monitoring system */ async start() { this.logger.info('🚀 Starting Enhanced Monitoring System...'); // Initialize monitoring tables await this.createMonitoringTables(); // Start real-time monitoring if (this.config.realTimeEnabled) { this.startRealTimeMonitoring(); } // Start alerting system if (this.config.alertingEnabled) { this.startAlertingSystem(); } // Start predictive analytics if (this.config.predictiveAnalyticsEnabled) { this.startPredictiveAnalytics(); } // Start dashboard server if (this.config.dashboardEnabled) { await this.startDashboardServer(); } // Set up performance tracker integration this.setupPerformanceTrackerIntegration(); this.logger.info('✅ Enhanced Monitoring System started successfully'); } /** * Get current system health status */ async getSystemHealth() { await this.updateSystemHealth(); return { ...this.systemHealth }; } /** * Get performance trends for specified periods */ async getPerformanceTrends(periods = ['hour', 'day', 'week']) { const trends = []; const metrics = [ 'response_time', 'throughput', 'error_rate', 'cpu_usage', 'memory_usage', 'cache_hit_rate' ]; for (const metric of metrics) { for (const period of periods) { const trend = await this.calculateTrend(metric, period); if (trend) { trends.push(trend); } } } return trends.sort((a, b) => { // Sort by severity: degrading trends first, then by impact if (a.trend === 'degrading' && b.trend !== 'degrading') return -1; if (b.trend === 'degrading' && a.trend !== 'degrading') return 1; return Math.abs(b.percentageChange) - Math.abs(a.percentageChange); }); } /** * Get resource usage forecasts */ async getResourceForecasts(timeHorizonHours = 24) { const forecasts = []; const resources = ['cpu', 'memory', 'disk', 'network', 'database_connections']; for (const resource of resources) { const forecast = await this.generateResourceForecast(resource, timeHorizonHours); if (forecast) { forecasts.push(forecast); } } return forecasts.sort((a, b) => { // Sort by urgency: resources approaching exhaustion first if (a.exhaustionDate && b.exhaustionDate) { return a.exhaustionDate.getTime() - b.exhaustionDate.getTime(); } if (a.exhaustionDate && !b.exhaustionDate) return -1; if (!a.exhaustionDate && b.exhaustionDate) return 1; return b.predictedUsage - a.predictedUsage; }); } /** * Generate comprehensive monitoring report */ async generateMonitoringReport(period = 'day') { this.logger.info('📊 Generating comprehensive monitoring report', { period }); const [systemHealth, performanceReport, trends, forecasts, alerts, recommendations] = await Promise.all([ this.getSystemHealth(), this.performanceTracker.generateReport(period), this.getPerformanceTrends([period]), this.getResourceForecasts(period === 'hour' ? 24 : 168), // 24h or 1 week this.getActiveAlerts(), this.generateSmartRecommendations() ]); const report = { timestamp: new Date(), period, summary: { overallHealth: systemHealth.overall, totalAlerts: alerts.length, criticalIssues: alerts.filter(a => a.severity === 'critical').length, performanceScore: this.calculatePerformanceScore(performanceReport, systemHealth), trendsCount: trends.length, forecastsCount: forecasts.length }, systemHealth, performance: performanceReport, trends: trends.slice(0, 10), // Top 10 trends forecasts: forecasts.slice(0, 5), // Top 5 forecasts alerts: alerts.slice(0, 20), // Recent 20 alerts recommendations: recommendations.slice(0, 10), // Top 10 recommendations metadata: { monitoringSystemVersion: '2.0.0', reportGenerationTime: Date.now() - Date.now(), // Will be updated at end includedComponents: Object.keys(systemHealth.components), dataPoints: await this.getDataPointCount(period) } }; // Update generation time report.metadata.reportGenerationTime = Date.now() - report.timestamp.getTime(); // Store report await this.memory.store(`monitoring_report_${period}_${Date.now()}`, report, this.config.retentionPeriods.dailyAggregates); this.logger.info('✅ Monitoring report generated', { period, overallHealth: systemHealth.overall, alertCount: alerts.length, generationTime: report.metadata.reportGenerationTime }); return report; } /** * Acknowledge an alert */ async acknowledgeAlert(alertId, acknowledgedBy) { const alert = this.activeAlerts.get(alertId); if (!alert) { return false; } alert.acknowledged = true; // Store acknowledgment await this.memory.store(`alert_ack_${alertId}`, { alertId, acknowledgedBy, acknowledgedAt: new Date(), alert: { ...alert } }); this.logger.info('🔔 Alert acknowledged', { alertId, acknowledgedBy }); // Broadcast to connected clients this.broadcastToClients({ type: 'alert_acknowledged', data: { alertId, acknowledgedBy, timestamp: new Date() } }); return true; } /** * Get active alerts */ async getActiveAlerts() { return Array.from(this.activeAlerts.values()) .sort((a, b) => { // Sort by severity, then by timestamp const severityOrder = { critical: 4, high: 3, medium: 2, low: 1 }; const severityDiff = severityOrder[b.severity] - severityOrder[a.severity]; if (severityDiff !== 0) return severityDiff; return b.timestamp.getTime() - a.timestamp.getTime(); }); } /** * Private Methods */ initializeSystemHealth() { return { overall: 'unknown', components: { cpu: { status: 'unknown', value: 0, threshold: 80, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' }, memory: { status: 'unknown', value: 0, threshold: 85, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' }, disk: { status: 'unknown', value: 0, threshold: 90, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' }, network: { status: 'unknown', value: 0, threshold: 80, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' }, database: { status: 'unknown', value: 0, threshold: 75, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' }, cache: { status: 'unknown', value: 0, threshold: 50, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' }, api: { status: 'unknown', value: 0, threshold: 5000, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' } }, alerts: [], recommendations: [], predictedIssues: [] }; } async createMonitoringTables() { await this.memory.execute(` CREATE TABLE IF NOT EXISTS monitoring_metrics ( id TEXT PRIMARY KEY, metric_name TEXT NOT NULL, metric_value REAL NOT NULL, component TEXT NOT NULL, timestamp INTEGER NOT NULL, metadata TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_monitoring_metrics_name ON monitoring_metrics(metric_name); CREATE INDEX IF NOT EXISTS idx_monitoring_metrics_timestamp ON monitoring_metrics(timestamp); CREATE INDEX IF NOT EXISTS idx_monitoring_metrics_component ON monitoring_metrics(component); CREATE TABLE IF NOT EXISTS monitoring_alerts ( id TEXT PRIMARY KEY, severity TEXT NOT NULL, component TEXT NOT NULL, message TEXT NOT NULL, timestamp INTEGER NOT NULL, acknowledged BOOLEAN DEFAULT FALSE, acknowledged_by TEXT, acknowledged_at INTEGER, count INTEGER DEFAULT 1, first_seen INTEGER NOT NULL, last_seen INTEGER NOT NULL, metadata TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_monitoring_alerts_severity ON monitoring_alerts(severity); CREATE INDEX IF NOT EXISTS idx_monitoring_alerts_component ON monitoring_alerts(component); CREATE INDEX IF NOT EXISTS idx_monitoring_alerts_timestamp ON monitoring_alerts(timestamp); CREATE TABLE IF NOT EXISTS monitoring_predictions ( id TEXT PRIMARY KEY, prediction_type TEXT NOT NULL, component TEXT NOT NULL, description TEXT NOT NULL, probability REAL NOT NULL, estimated_time INTEGER, impact TEXT NOT NULL, recommendations TEXT, confidence REAL NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); `); } startRealTimeMonitoring() { this.logger.info('🔄 Starting real-time monitoring...'); this.monitoringInterval = setInterval(async () => { try { await this.collectSystemMetrics(); await this.updateSystemHealth(); // Broadcast to connected clients if (this.connectedClients.size > 0) { this.broadcastToClients({ type: 'system_health_update', data: this.systemHealth }); } } catch (error) { this.logger.error('❌ Error in real-time monitoring:', error); } }, 5000); // Every 5 seconds } startAlertingSystem() { this.logger.info('🔔 Starting alerting system...'); this.alertingInterval = setInterval(async () => { try { await this.checkAlertConditions(); await this.cleanupOldAlerts(); } catch (error) { this.logger.error('❌ Error in alerting system:', error); } }, 10000); // Every 10 seconds } startPredictiveAnalytics() { this.logger.info('🔮 Starting predictive analytics...'); this.predictionInterval = setInterval(async () => { try { await this.runPredictiveAnalysis(); } catch (error) { this.logger.error('❌ Error in predictive analytics:', error); } }, 300000); // Every 5 minutes } async startDashboardServer() { this.httpServer = http_1.default.createServer((req, res) => { this.handleHttpRequest(req, res); }); this.websocketServer = new ws_1.default.Server({ server: this.httpServer, path: '/monitoring-ws' }); this.websocketServer.on('connection', (ws) => { this.handleWebSocketConnection(ws); }); return new Promise((resolve) => { this.httpServer.listen(this.config.websocketPort, () => { this.logger.info(`🌐 Dashboard server started on port ${this.config.websocketPort}`); resolve(); }); }); } setupPerformanceTrackerIntegration() { // Listen to performance tracker events this.performanceTracker.on('performance:slow', (data) => { this.createAlert('high', 'api', `Slow operation detected: ${data.operation} (${data.duration}ms)`, data); }); this.performanceTracker.on('performance:failure', (data) => { this.createAlert('medium', 'api', `Operation failed: ${data.operation} - ${data.error}`, data); }); this.performanceTracker.on('performance:high-memory', (data) => { this.createAlert('medium', 'memory', `High memory usage: ${data.operation} (${data.memoryUsage}MB)`, data); }); this.performanceTracker.on('resource:warning', (data) => { this.createAlert('high', data.type, `Resource warning: ${data.type} usage at ${(data.usage * 100).toFixed(1)}%`, data); }); } async collectSystemMetrics() { const timestamp = Date.now(); // Collect Node.js process metrics const memUsage = process.memoryUsage(); const cpuUsage = process.cpuUsage(); const metrics = [ { name: 'process_memory_heap_used', value: memUsage.heapUsed / 1024 / 1024, // MB component: 'memory' }, { name: 'process_memory_heap_total', value: memUsage.heapTotal / 1024 / 1024, // MB component: 'memory' }, { name: 'process_memory_rss', value: memUsage.rss / 1024 / 1024, // MB component: 'memory' }, { name: 'process_cpu_user', value: cpuUsage.user / 1000, // milliseconds component: 'cpu' }, { name: 'process_cpu_system', value: cpuUsage.system / 1000, // milliseconds component: 'cpu' } ]; // Collect memory system metrics const memoryStats = await this.memory.getDatabaseStats(); metrics.push({ name: 'database_size', value: memoryStats.size / 1024 / 1024, // MB component: 'database' }); // Collect cache metrics if available try { const cacheStats = await this.memory.getCacheStats(); metrics.push({ name: 'cache_hit_rate', value: cacheStats.hits / (cacheStats.hits + cacheStats.misses) * 100, component: 'cache' }, { name: 'cache_size', value: cacheStats.size, component: 'cache' }); } catch (error) { // Cache stats may not be available } // Store metrics for (const metric of metrics) { await this.storeMetric(metric.name, metric.value, metric.component, timestamp); // Update history for trend analysis const historyKey = `${metric.component}_${metric.name}`; if (!this.metricHistory.has(historyKey)) { this.metricHistory.set(historyKey, []); } const history = this.metricHistory.get(historyKey); history.push(metric.value); // Keep only last 100 values if (history.length > 100) { history.shift(); } } } async storeMetric(name, value, component, timestamp) { const id = `${component}_${name}_${timestamp}`; await this.memory.insert('monitoring_metrics', { id, metric_name: name, metric_value: value, component, timestamp, metadata: JSON.stringify({ node_version: process.version, platform: process.platform, arch: process.arch }) }); } async updateSystemHealth() { const now = new Date(); // Update CPU health const cpuHistory = this.metricHistory.get('cpu_process_cpu_user') || []; if (cpuHistory.length > 0) { const currentCpu = cpuHistory[cpuHistory.length - 1] || 0; this.systemHealth.components.cpu = { status: currentCpu > this.config.alertThresholds.cpuUsage ? 'critical' : currentCpu > this.config.alertThresholds.cpuUsage * 0.8 ? 'warning' : 'healthy', value: currentCpu, threshold: this.config.alertThresholds.cpuUsage, trend: this.calculateComponentTrend('cpu', cpuHistory), lastUpdated: now, details: `CPU usage: ${currentCpu.toFixed(1)}%` }; } // Update Memory health const memHistory = this.metricHistory.get('memory_process_memory_heap_used') || []; if (memHistory.length > 0) { const currentMem = memHistory[memHistory.length - 1] || 0; this.systemHealth.components.memory = { status: currentMem > 500 ? 'critical' : currentMem > 300 ? 'warning' : 'healthy', value: currentMem, threshold: 500, trend: this.calculateComponentTrend('memory', memHistory), lastUpdated: now, details: `Heap usage: ${currentMem.toFixed(1)}MB` }; } // Update Database health const dbHistory = this.metricHistory.get('database_database_size') || []; if (dbHistory.length > 0) { const currentDb = dbHistory[dbHistory.length - 1] || 0; this.systemHealth.components.database = { status: currentDb > 1000 ? 'warning' : 'healthy', value: currentDb, threshold: 1000, trend: this.calculateComponentTrend('database', dbHistory), lastUpdated: now, details: `Database size: ${currentDb.toFixed(1)}MB` }; } // Update Cache health const cacheHitHistory = this.metricHistory.get('cache_cache_hit_rate') || []; if (cacheHitHistory.length > 0) { const currentHitRate = cacheHitHistory[cacheHitHistory.length - 1] || 0; this.systemHealth.components.cache = { status: currentHitRate < this.config.alertThresholds.cacheHitRate ? 'warning' : 'healthy', value: currentHitRate, threshold: this.config.alertThresholds.cacheHitRate, trend: this.calculateComponentTrend('cache', cacheHitHistory), lastUpdated: now, details: `Cache hit rate: ${currentHitRate.toFixed(1)}%` }; } // Calculate overall health const componentStatuses = Object.values(this.systemHealth.components).map(c => c.status); if (componentStatuses.includes('critical')) { this.systemHealth.overall = 'critical'; } else if (componentStatuses.includes('warning')) { this.systemHealth.overall = 'warning'; } else if (componentStatuses.every(s => s === 'healthy')) { this.systemHealth.overall = 'healthy'; } else { this.systemHealth.overall = 'unknown'; } // Update alerts list this.systemHealth.alerts = await this.getActiveAlerts(); } calculateComponentTrend(component, history) { if (history.length < 10) return 'stable'; const recent = history.slice(-5); const older = history.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; const changePercent = ((recentAvg - olderAvg) / olderAvg) * 100; // For CPU, memory, response time: increasing is degrading // For cache hit rate, throughput: increasing is improving const isInverseMetric = component.includes('cache') || component.includes('throughput'); if (Math.abs(changePercent) < 5) return 'stable'; if (isInverseMetric) { return changePercent > 0 ? 'improving' : 'degrading'; } else { return changePercent > 0 ? 'degrading' : 'improving'; } } async checkAlertConditions() { const now = Date.now(); // Check each component health for (const [componentName, component] of Object.entries(this.systemHealth.components)) { if (component.status === 'critical' || component.status === 'warning') { const severity = component.status === 'critical' ? 'critical' : 'high'; const alertId = `${componentName}_${component.status}`; if (this.activeAlerts.has(alertId)) { // Update existing alert const alert = this.activeAlerts.get(alertId); alert.count++; alert.lastSeen = new Date(); } else { // Create new alert await this.createAlert(severity, componentName, component.details, { threshold: component.threshold, currentValue: component.value, trend: component.trend }); } } } } async createAlert(severity, component, message, metadata) { const alertId = `${component}_${severity}_${Date.now()}`; const now = new Date(); const alert = { id: alertId, severity, component, message, timestamp: now, acknowledged: false, count: 1, firstSeen: now }; this.activeAlerts.set(alertId, alert); // Store in database await this.memory.insert('monitoring_alerts', { id: alertId, severity, component, message, timestamp: now.getTime(), acknowledged: false, count: 1, first_seen: now.getTime(), last_seen: now.getTime(), metadata: JSON.stringify(metadata || {}) }); this.logger.warn(`🚨 Alert created: ${severity.toUpperCase()} - ${component} - ${message}`, { alertId }); // Emit alert event this.emit('alert', alert); // Broadcast to connected clients this.broadcastToClients({ type: 'new_alert', data: alert }); } async cleanupOldAlerts() { const cutoff = Date.now() - (24 * 60 * 60 * 1000); // 24 hours for (const [alertId, alert] of this.activeAlerts) { if (alert.timestamp.getTime() < cutoff && alert.acknowledged) { this.activeAlerts.delete(alertId); } } } async runPredictiveAnalysis() { this.logger.debug('🔮 Running predictive _analysis...'); const predictions = []; // Analyze memory growth const memHistory = this.metricHistory.get('memory_process_memory_heap_used') || []; if (memHistory.length > 20) { const memoryPrediction = this.predictResourceExhaustion('memory', memHistory, 1000); // 1GB limit if (memoryPrediction) { predictions.push(memoryPrediction); } } // Analyze database growth const dbHistory = this.metricHistory.get('database_database_size') || []; if (dbHistory.length > 20) { const dbPrediction = this.predictResourceExhaustion('database', dbHistory, 5000); // 5GB limit if (dbPrediction) { predictions.push(dbPrediction); } } // Store predictions for (const prediction of predictions) { await this.memory.insert('monitoring_predictions', { id: `prediction_${prediction.type}_${prediction.component}_${Date.now()}`, prediction_type: prediction.type, component: prediction.component, description: prediction.description, probability: prediction.probability, estimated_time: prediction.estimatedTime?.getTime(), impact: prediction.impact, recommendations: JSON.stringify(prediction.recommendations), confidence: prediction.probability }); } // Update system health with predictions this.systemHealth.predictedIssues = predictions; } predictResourceExhaustion(resource, history, limit) { if (history.length < 10) return null; // Simple linear regression to predict growth const recentHistory = history.slice(-20); const n = recentHistory.length; const x = Array.from({ length: n }, (_, i) => i); const y = recentHistory; const sumX = x.reduce((a, b) => a + b, 0); const sumY = y.reduce((a, b) => a + b, 0); const sumXY = x.reduce((sum, xi, i) => sum + xi * y[i], 0); const sumXX = x.reduce((sum, xi) => sum + xi * xi, 0); const slope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX); const intercept = (sumY - slope * sumX) / n; // Predict when resource will reach limit if (slope > 0) { const currentValue = y[y.length - 1]; const timeToLimit = (limit - currentValue) / slope; if (timeToLimit > 0 && timeToLimit < 1000) { // Within 1000 time units const probability = Math.min(0.9, Math.max(0.1, 1 - (timeToLimit / 1000))); const estimatedTime = new Date(Date.now() + (timeToLimit * 300000)); // 5-minute intervals return { type: 'resource_exhaustion', component: resource, description: `${resource} usage is growing and may reach capacity limits`, probability, estimatedTime, impact: timeToLimit < 100 ? 'critical' : timeToLimit < 300 ? 'high' : 'medium', recommendations: [ `Monitor ${resource} usage closely`, `Consider optimizing ${resource} consumption`, 'Implement cleanup/archival processes', 'Scale resources if necessary' ] }; } } return null; } async calculateTrend(metric, period) { const timeframe = { hour: 3600000, day: 86400000, week: 604800000 }[period]; const since = Date.now() - timeframe; const metrics = await this.memory.query(` SELECT metric_value, timestamp FROM monitoring_metrics WHERE metric_name = ? AND timestamp > ? ORDER BY timestamp `, [metric, since]); if (metrics.length < 10) return null; const values = metrics.map(m => m.metric_value); const recent = values.slice(-Math.floor(values.length / 3)); const older = values.slice(0, Math.floor(values.length / 3)); const recentAvg = recent.reduce((a, b) => a + b, 0) / recent.length; const olderAvg = older.reduce((a, b) => a + b, 0) / older.length; const overallAvg = values.reduce((a, b) => a + b, 0) / values.length; const percentageChange = ((recentAvg - olderAvg) / olderAvg) * 100; const variance = values.reduce((sum, val) => sum + Math.pow(val - overallAvg, 2), 0) / values.length; const volatility = Math.sqrt(variance) / overallAvg; return { metric, period, trend: Math.abs(percentageChange) < 5 ? 'stable' : percentageChange > 0 ? 'degrading' : 'improving', percentageChange, currentValue: recentAvg, historicalAverage: overallAvg, volatility }; } async generateResourceForecast(resource, timeHorizonHours) { const history = this.metricHistory.get(`${resource}_${resource}_usage`) || this.metricHistory.get(`${resource}_process_memory_heap_used`) || this.metricHistory.get(`${resource}_database_size`) || []; if (history.length < 10) return null; const currentUsage = history[history.length - 1] || 0; const trend = this.calculateComponentTrend(resource, history); // Simple prediction based on trend let predictedUsage = currentUsage; let confidence = 0.5; if (trend === 'degrading') { const growthRate = this.calculateGrowthRate(history); predictedUsage = currentUsage * (1 + (growthRate * timeHorizonHours / 24)); confidence = 0.7; } else if (trend === 'improving') { const reductionRate = this.calculateGrowthRate(history); predictedUsage = currentUsage * (1 + (reductionRate * timeHorizonHours / 24)); confidence = 0.6; } const recommendations = []; let exhaustionDate; if (predictedUsage > currentUsage * 1.5) { recommendations.push(`${resource} usage expected to increase significantly`); recommendations.push('Consider implementing resource optimization'); } if (predictedUsage > 1000) { // Arbitrary threshold exhaustionDate = new Date(Date.now() + (timeHorizonHours * 3600000)); recommendations.push('Resource exhaustion predicted - immediate action required'); } return { resource, currentUsage, predictedUsage, timeHorizon: timeHorizonHours, confidence, exhaustionDate, recommendations }; } calculateGrowthRate(history) { if (history.length < 5) return 0; const recent = history.slice(-5); const older = history.slice(-10, -5); const recentAvg = recent.reduce((a, b) => a + b) / recent.length; const olderAvg = older.reduce((a, b) => a + b) / older.length; return (recentAvg - olderAvg) / olderAvg; } calculatePerformanceScore(performanceReport, systemHealth) { let score = 100; // Deduct points for errors score -= performanceReport.summary.errorRate * 2; // Deduct points for slow response times if (performanceReport.summary.averageResponseTime > 2000) { score -= (performanceReport.summary.averageResponseTime - 2000) / 100; } // Deduct points for unhealthy components const unhealthyComponents = Object.values(systemHealth.components) .filter(c => c.status !== 'healthy').length; score -= unhealthyComponents * 10; // Deduct points for critical alerts const criticalAlerts = systemHealth.alerts.filter(a => a.severity === 'critical').length; score -= criticalAlerts * 15; return Math.max(0, Math.min(100, score)); } async generateSmartRecommendations() { const recommendations = []; // Analyze system health and generate recommendations for (const [componentName, component] of Object.entries(this.systemHealth.components)) { if (component.status !== 'healthy') { if (componentName === 'memory' && component.trend === 'degrading') { recommendations.push('Consider implementing memory optimization strategies'); recommendations.push('Review memory leaks in long-running processes'); } if (componentName === 'cpu' && component.value > 80) { recommendations.push('CPU usage is high - consider scaling or optimization'); } if (componentName === 'cache' && component.value < 50) { recommendations.push('Cache hit rate is low - review caching strategy'); } } } // Add predictive recommendations for (const prediction of this.systemHealth.predictedIssues) { recommendations.push(...prediction.recommendations); } return [...new Set(recommendations)]; // Remove duplicates } async getDataPointCount(period) { const timeframe = { hour: 3600000, day: 86400000, week: 604800000, month: 2592000000 }[period] || 86400000; const since = Date.now() - timeframe; const result = await this.memory.query(` SELECT COUNT(*) as count FROM monitoring_metrics WHERE timestamp > ? `, [since]); return result[0]?.count || 0; } handleWebSocketConnection(ws) { this.connectedClients.add(ws); this.logger.info('📱 WebSocket client connected', { totalClients: this.connectedClients.size }); // Send initial system health ws.send(JSON.stringify({ type: 'initial_data', data: { systemHealth: this.systemHealth, timestamp: new Date() } })); ws.on('close', () => { this.connectedClients.delete(ws); this.logger.info('📱 WebSocket client disconnected', { totalClients: this.connectedClients.size }); }); ws.on('message', async (message) => { try { const data = JSON.parse(message.toString()); await this.handleWebSocketMessage(ws, data); } catch (error) { this.logger.error('❌ Error handling WebSocket message:', error); } }); } async handleWebSocketMessage(ws, message) { switch (message.type) { case 'acknowledge_alert': if (message.alertId && message.user) { const success = await this.acknowledgeAlert(message.alertId, message.user); ws.send(JSON.stringify({ type: 'alert_acknowledged', success, alertId: message.alertId })); } break; case 'get_performance_trends': const trends = await this.getPerformanceTrends(message.periods || ['day']); ws.send(JSON.stringify({ type: 'performance_trends', data: trends })); break; case 'get_resource_forecasts': const forecasts = await this.getResourceForecasts(message.timeHorizon || 24); ws.send(JSON.stringify({ type: 'resource_forecasts', data: forecasts })); break; } } handleHttpRequest(req, res) { // Serve basic monitoring dashboard const dashboardHtml = this.generateDashboardHtml(); res.writeHead(200, { 'Content-Type': 'text/html', 'Content-Length': Buffer.byteLength(dashboardHtml) }); res.end(dashboardHtml); } generateDashboardHtml() { return ` <!DOCTYPE html> <html> <head> <title>Snow-Flow Enhanced Monitoring Dashboard</title> <style> body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; } .header { background: #2c3e50; color: white; padding: 20px; border-radius: 5px; margin-bottom: 20px; } .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; } .card { background: white; padding: 20px; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } .status-healthy { color: #27ae60; } .status-warning { color: #f39c12; } .status-critical { color: #e74c3c; } .status-unknown { color: #95a5a6; } .metric { display: flex; justify-content: space-between; margin: 10px 0; } .alert { padding: 10px; margin: 5px 0; border-radius: 3px; } .alert-critical { background: #ffebee; border-left: 4px solid #e74c3c; } .alert-high { background: #fff3e0; border-left: 4px solid #ff9800; } .alert-medium { background: #f3e5f5; border-left: 4px solid #9c27b0; } .alert-low { background: #e8f5e8; border-left: 4px solid #4caf50; } #connectionStatus { position: fixed; top: 10px; right: 10px; padding: 5px 10px; border-radius: 3px; } .connected { background: #4caf50; color: white; } .disconnected { background: #f44336; color: white; } </style> </head> <body> <div class="header"> <h1>🚀 Snow-Flow Enhanced Monitoring Dashboard</h1> <p>Real-time system health and performance monitoring</p> <div id="connectionStatus" class="disconnected">Connecting...</div> </div> <div class="grid"> <div class="card"> <h3>System Health Overview</h3> <div id="overallHealth">Loading...</div> <div id="componentHealth"></div> </div> <div class="card"> <h3>Active Alerts</h3> <div id="alerts">Loading...</div> </div> <div class="card"> <h3>Performance Metrics</h3> <div id="performanceMetrics">Loading...</div> </div> <div class="card"> <h3>Resource Usage</h3> <div id="resourceUsage">Loading...</div> </div> </div> <script> const ws = new WebSocket('ws://localhost:${this.config.websocketPort}/monitoring-ws'); const connectionStatus = document.getElementById('connectionStatus'); ws.onopen = function() { connectionStatus.textContent = 'Connected'; connectionStatus.className = 'connected'; }; ws.onclose = function() { connectionStatus.textContent = 'Disconnected'; connectionStatus.className = 'disconnected'; }; ws.onmessage = function(event) { const message = JSON.parse(event.data); switch(message.type) { case 'initial_data': case 'system_health_update': updateSystemHealth(message.data.systemHealth || message.data); break; case 'new_alert': addAlert(message.data); break; } }; function updateSystemHealth(health) { // Update overall health const overallHealth = document.getElementById('overallHealth'); overallHealth.innerHTML = \` <div class="metric"> <span>Overall Status:</span> <span class="status-\${health.overall}">\${health.overall.toUpperCase()}</span> </div> \`; // Update component health const componentHealth = document.getElementById('componentHealth'); let componentsHtml = ''; for (const [name, component] of Object.entries(health.components)) { componentsHtml += \` <div class="metric"> <span>\${name.charAt(0).toUpperCase() + name.slice(1)}:</span> <span class="status-\${component.status}"> \${component.value.toFixed(1)} (\${component.status}) </span> </div> \`; } componentHealth.innerHTML = componentsHtml; // Update alerts updateAlerts(health.alerts || []); } function updateAlerts(alerts) { const alertsDiv = document.getElementById('alerts'); if (alerts.length === 0) { alertsDiv.innerHTML = '<p>No active alerts</p>'; return; } let alertsHtml = ''; alerts.slice(0, 10).forEach(alert => { alertsHtml += \` <div class="alert alert-\${alert.severity}"> <strong>\${alert.component.toUpperCase()}</strong>: \${alert.message} <br><small>\${new Date(alert.timestamp).toLocaleString()}</small> </div> \`; }); alertsDiv.innerHTML = alertsHtml; } function addAlert(alert) { // Add new alert to the top of the list const alertsDiv = document.getElementById('alerts'); const newAlertHtml = \` <div class="alert alert-\${alert.severity}"> <strong>\${alert.component.toUpperCase()}</strong>: \${alert.message} <br><small>\${new Date(alert.timestamp).toLocaleString()}</small> </div> \`; alertsDiv.innerHTML = newAlertHtml + alertsDiv.innerHTML; } </script> </body> </html> `; } broadcastToClients(message) { const messageStr = JSON.stringify(message); this.connectedClients.forEach(client => { if (client.readyState === ws_1.default.OPEN) { client.send(messageStr); } }); } /** * Shutdown the monitoring system */ async shutdown() { this.logger.info('🛑 Shutting down Enhanced Monitoring System...'); // Clear intervals if (this.monitoringInterval) clearInterval(this.monitoringInterval); if (this.alertingInterval) clearInterval(this.alertingInterval); if (this.predictionInterval) clearInterval(this.predictionInterval); // Close WebSocket connections this.connectedClients.forEach(client => { client.close(); }); this.connectedClients.clear(); // Close servers if (this.websocketServer) { this.websocketServer.close(); } if (this.httpServer) { this.httpServer.close(); } this.logger.info('✅ Enhanced Monitoring System shut down'); } } exports.EnhancedMonitoringSystem = EnhancedMonitoringSystem; //# sourceMappingURL=enhanced-monitoring-system.js.map