snow-flow 1.3.25 → 1.3.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/.claude/config.json +33 -9
  2. package/.claude-flow/queen/queen-memory.db +0 -0
  3. package/.roo/README.md +56 -0
  4. package/.roo/workflows/basic-tdd.json +32 -0
  5. package/.roomodes +122 -0
  6. package/CLAUDE.md +140 -752
  7. package/claude-flow +30 -75
  8. package/dist/cli.js +250 -7
  9. package/dist/compliance/advanced-compliance-system.js +857 -0
  10. package/dist/compliance/index.js +8 -0
  11. package/dist/documentation/index.js +8 -0
  12. package/dist/documentation/self-documenting-system.js +1006 -0
  13. package/dist/healing/index.js +8 -0
  14. package/dist/healing/self-healing-system.js +1041 -0
  15. package/dist/intelligence/performance-recommendations-engine.js +479 -4
  16. package/dist/managers/scope-manager.js +5 -2
  17. package/dist/mcp/servicenow-deployment-mcp.js +113 -15
  18. package/dist/mcp/servicenow-flow-composer-mcp.js +4 -2
  19. package/dist/mcp/servicenow-intelligent-mcp.js +351 -0
  20. package/dist/mcp/servicenow-operations-mcp.js +2 -2
  21. package/dist/memory/memory-system.js +146 -0
  22. package/dist/monitoring/enhanced-monitoring-system.js +1085 -0
  23. package/dist/optimization/cost-optimization-engine.js +771 -0
  24. package/dist/optimization/flow-performance-optimizer.js +723 -0
  25. package/dist/optimization/index.js +10 -0
  26. package/dist/orchestration/flow-update-orchestrator.js +648 -0
  27. package/dist/rollback/smart-rollback-system.js +462 -0
  28. package/dist/templates/flow-template-system.js +625 -0
  29. package/dist/testing/flow-testing-automation.js +641 -0
  30. package/dist/testing/integration-test-suite.js +890 -0
  31. package/dist/utils/flow-structure-builder.js +1 -1
  32. package/dist/utils/servicenow-client.js +50 -2
  33. package/dist/utils/snow-oauth.js +66 -8
  34. package/dist/utils/xml-first-flow-generator.js +6 -0
  35. package/dist/version.js +13 -1
  36. package/package.json +1 -1
@@ -0,0 +1,1085 @@
1
+ "use strict";
2
+ /**
3
+ * 🚀 PERFORMANCE FIX: Enhanced Monitoring System
4
+ * Advanced real-time monitoring with predictive analytics, alerting, and dashboards
5
+ *
6
+ * Addresses beta testing feedback on performance monitoring gaps
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.EnhancedMonitoringSystem = void 0;
13
+ const events_1 = require("events");
14
+ const logger_1 = require("../utils/logger");
15
+ const ws_1 = __importDefault(require("ws"));
16
+ const http_1 = __importDefault(require("http"));
17
+ class EnhancedMonitoringSystem extends events_1.EventEmitter {
18
+ constructor(performanceTracker, memory, config) {
19
+ super();
20
+ this.activeAlerts = new Map();
21
+ this.metricHistory = new Map();
22
+ this.connectedClients = new Set();
23
+ this.performanceTracker = performanceTracker;
24
+ this.memory = memory;
25
+ this.logger = new logger_1.Logger('EnhancedMonitoringSystem');
26
+ this.config = {
27
+ realTimeEnabled: true,
28
+ predictiveAnalyticsEnabled: true,
29
+ alertingEnabled: true,
30
+ dashboardEnabled: true,
31
+ websocketPort: 8090,
32
+ alertThresholds: {
33
+ cpuUsage: 80,
34
+ memoryUsage: 85,
35
+ diskUsage: 90,
36
+ responseTime: 5000,
37
+ errorRate: 10,
38
+ cacheHitRate: 50,
39
+ queueDepth: 100
40
+ },
41
+ retentionPeriods: {
42
+ realTimeMetrics: 3600000, // 1 hour
43
+ hourlyAggregates: 2592000000, // 30 days
44
+ dailyAggregates: 7776000000, // 90 days
45
+ weeklyAggregates: 31536000000 // 1 year
46
+ },
47
+ ...config
48
+ };
49
+ this.systemHealth = this.initializeSystemHealth();
50
+ this.logger.info('🚀 Enhanced Monitoring System initialized', {
51
+ realTimeEnabled: this.config.realTimeEnabled,
52
+ predictiveAnalyticsEnabled: this.config.predictiveAnalyticsEnabled,
53
+ alertingEnabled: this.config.alertingEnabled,
54
+ dashboardEnabled: this.config.dashboardEnabled
55
+ });
56
+ }
57
+ /**
58
+ * Start the enhanced monitoring system
59
+ */
60
+ async start() {
61
+ this.logger.info('🚀 Starting Enhanced Monitoring System...');
62
+ // Initialize monitoring tables
63
+ await this.createMonitoringTables();
64
+ // Start real-time monitoring
65
+ if (this.config.realTimeEnabled) {
66
+ this.startRealTimeMonitoring();
67
+ }
68
+ // Start alerting system
69
+ if (this.config.alertingEnabled) {
70
+ this.startAlertingSystem();
71
+ }
72
+ // Start predictive analytics
73
+ if (this.config.predictiveAnalyticsEnabled) {
74
+ this.startPredictiveAnalytics();
75
+ }
76
+ // Start dashboard server
77
+ if (this.config.dashboardEnabled) {
78
+ await this.startDashboardServer();
79
+ }
80
+ // Set up performance tracker integration
81
+ this.setupPerformanceTrackerIntegration();
82
+ this.logger.info('✅ Enhanced Monitoring System started successfully');
83
+ }
84
+ /**
85
+ * Get current system health status
86
+ */
87
+ async getSystemHealth() {
88
+ await this.updateSystemHealth();
89
+ return { ...this.systemHealth };
90
+ }
91
+ /**
92
+ * Get performance trends for specified periods
93
+ */
94
+ async getPerformanceTrends(periods = ['hour', 'day', 'week']) {
95
+ const trends = [];
96
+ const metrics = [
97
+ 'response_time',
98
+ 'throughput',
99
+ 'error_rate',
100
+ 'cpu_usage',
101
+ 'memory_usage',
102
+ 'cache_hit_rate'
103
+ ];
104
+ for (const metric of metrics) {
105
+ for (const period of periods) {
106
+ const trend = await this.calculateTrend(metric, period);
107
+ if (trend) {
108
+ trends.push(trend);
109
+ }
110
+ }
111
+ }
112
+ return trends.sort((a, b) => {
113
+ // Sort by severity: degrading trends first, then by impact
114
+ if (a.trend === 'degrading' && b.trend !== 'degrading')
115
+ return -1;
116
+ if (b.trend === 'degrading' && a.trend !== 'degrading')
117
+ return 1;
118
+ return Math.abs(b.percentageChange) - Math.abs(a.percentageChange);
119
+ });
120
+ }
121
+ /**
122
+ * Get resource usage forecasts
123
+ */
124
+ async getResourceForecasts(timeHorizonHours = 24) {
125
+ const forecasts = [];
126
+ const resources = ['cpu', 'memory', 'disk', 'network', 'database_connections'];
127
+ for (const resource of resources) {
128
+ const forecast = await this.generateResourceForecast(resource, timeHorizonHours);
129
+ if (forecast) {
130
+ forecasts.push(forecast);
131
+ }
132
+ }
133
+ return forecasts.sort((a, b) => {
134
+ // Sort by urgency: resources approaching exhaustion first
135
+ if (a.exhaustionDate && b.exhaustionDate) {
136
+ return a.exhaustionDate.getTime() - b.exhaustionDate.getTime();
137
+ }
138
+ if (a.exhaustionDate && !b.exhaustionDate)
139
+ return -1;
140
+ if (!a.exhaustionDate && b.exhaustionDate)
141
+ return 1;
142
+ return b.predictedUsage - a.predictedUsage;
143
+ });
144
+ }
145
+ /**
146
+ * Generate comprehensive monitoring report
147
+ */
148
+ async generateMonitoringReport(period = 'day') {
149
+ this.logger.info('📊 Generating comprehensive monitoring report', { period });
150
+ const [systemHealth, performanceReport, trends, forecasts, alerts, recommendations] = await Promise.all([
151
+ this.getSystemHealth(),
152
+ this.performanceTracker.generateReport(period),
153
+ this.getPerformanceTrends([period]),
154
+ this.getResourceForecasts(period === 'hour' ? 24 : 168), // 24h or 1 week
155
+ this.getActiveAlerts(),
156
+ this.generateSmartRecommendations()
157
+ ]);
158
+ const report = {
159
+ timestamp: new Date(),
160
+ period,
161
+ summary: {
162
+ overallHealth: systemHealth.overall,
163
+ totalAlerts: alerts.length,
164
+ criticalIssues: alerts.filter(a => a.severity === 'critical').length,
165
+ performanceScore: this.calculatePerformanceScore(performanceReport, systemHealth),
166
+ trendsCount: trends.length,
167
+ forecastsCount: forecasts.length
168
+ },
169
+ systemHealth,
170
+ performance: performanceReport,
171
+ trends: trends.slice(0, 10), // Top 10 trends
172
+ forecasts: forecasts.slice(0, 5), // Top 5 forecasts
173
+ alerts: alerts.slice(0, 20), // Recent 20 alerts
174
+ recommendations: recommendations.slice(0, 10), // Top 10 recommendations
175
+ metadata: {
176
+ monitoringSystemVersion: '2.0.0',
177
+ reportGenerationTime: Date.now() - Date.now(), // Will be updated at end
178
+ includedComponents: Object.keys(systemHealth.components),
179
+ dataPoints: await this.getDataPointCount(period)
180
+ }
181
+ };
182
+ // Update generation time
183
+ report.metadata.reportGenerationTime = Date.now() - report.timestamp.getTime();
184
+ // Store report
185
+ await this.memory.store(`monitoring_report_${period}_${Date.now()}`, report, this.config.retentionPeriods.dailyAggregates);
186
+ this.logger.info('✅ Monitoring report generated', {
187
+ period,
188
+ overallHealth: systemHealth.overall,
189
+ alertCount: alerts.length,
190
+ generationTime: report.metadata.reportGenerationTime
191
+ });
192
+ return report;
193
+ }
194
+ /**
195
+ * Acknowledge an alert
196
+ */
197
+ async acknowledgeAlert(alertId, acknowledgedBy) {
198
+ const alert = this.activeAlerts.get(alertId);
199
+ if (!alert) {
200
+ return false;
201
+ }
202
+ alert.acknowledged = true;
203
+ // Store acknowledgment
204
+ await this.memory.store(`alert_ack_${alertId}`, {
205
+ alertId,
206
+ acknowledgedBy,
207
+ acknowledgedAt: new Date(),
208
+ alert: { ...alert }
209
+ });
210
+ this.logger.info('🔔 Alert acknowledged', { alertId, acknowledgedBy });
211
+ // Broadcast to connected clients
212
+ this.broadcastToClients({
213
+ type: 'alert_acknowledged',
214
+ data: { alertId, acknowledgedBy, timestamp: new Date() }
215
+ });
216
+ return true;
217
+ }
218
+ /**
219
+ * Get active alerts
220
+ */
221
+ async getActiveAlerts() {
222
+ return Array.from(this.activeAlerts.values())
223
+ .sort((a, b) => {
224
+ // Sort by severity, then by timestamp
225
+ const severityOrder = { critical: 4, high: 3, medium: 2, low: 1 };
226
+ const severityDiff = severityOrder[b.severity] - severityOrder[a.severity];
227
+ if (severityDiff !== 0)
228
+ return severityDiff;
229
+ return b.timestamp.getTime() - a.timestamp.getTime();
230
+ });
231
+ }
232
+ /**
233
+ * Private Methods
234
+ */
235
+ initializeSystemHealth() {
236
+ return {
237
+ overall: 'unknown',
238
+ components: {
239
+ cpu: { status: 'unknown', value: 0, threshold: 80, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' },
240
+ memory: { status: 'unknown', value: 0, threshold: 85, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' },
241
+ disk: { status: 'unknown', value: 0, threshold: 90, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' },
242
+ network: { status: 'unknown', value: 0, threshold: 80, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' },
243
+ database: { status: 'unknown', value: 0, threshold: 75, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' },
244
+ cache: { status: 'unknown', value: 0, threshold: 50, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' },
245
+ api: { status: 'unknown', value: 0, threshold: 5000, trend: 'stable', lastUpdated: new Date(), details: 'Initializing...' }
246
+ },
247
+ alerts: [],
248
+ recommendations: [],
249
+ predictedIssues: []
250
+ };
251
+ }
252
+ async createMonitoringTables() {
253
+ await this.memory.execute(`
254
+ CREATE TABLE IF NOT EXISTS monitoring_metrics (
255
+ id TEXT PRIMARY KEY,
256
+ metric_name TEXT NOT NULL,
257
+ metric_value REAL NOT NULL,
258
+ component TEXT NOT NULL,
259
+ timestamp INTEGER NOT NULL,
260
+ metadata TEXT,
261
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
262
+ );
263
+
264
+ CREATE INDEX IF NOT EXISTS idx_monitoring_metrics_name ON monitoring_metrics(metric_name);
265
+ CREATE INDEX IF NOT EXISTS idx_monitoring_metrics_timestamp ON monitoring_metrics(timestamp);
266
+ CREATE INDEX IF NOT EXISTS idx_monitoring_metrics_component ON monitoring_metrics(component);
267
+
268
+ CREATE TABLE IF NOT EXISTS monitoring_alerts (
269
+ id TEXT PRIMARY KEY,
270
+ severity TEXT NOT NULL,
271
+ component TEXT NOT NULL,
272
+ message TEXT NOT NULL,
273
+ timestamp INTEGER NOT NULL,
274
+ acknowledged BOOLEAN DEFAULT FALSE,
275
+ acknowledged_by TEXT,
276
+ acknowledged_at INTEGER,
277
+ count INTEGER DEFAULT 1,
278
+ first_seen INTEGER NOT NULL,
279
+ last_seen INTEGER NOT NULL,
280
+ metadata TEXT,
281
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
282
+ );
283
+
284
+ CREATE INDEX IF NOT EXISTS idx_monitoring_alerts_severity ON monitoring_alerts(severity);
285
+ CREATE INDEX IF NOT EXISTS idx_monitoring_alerts_component ON monitoring_alerts(component);
286
+ CREATE INDEX IF NOT EXISTS idx_monitoring_alerts_timestamp ON monitoring_alerts(timestamp);
287
+
288
+ CREATE TABLE IF NOT EXISTS monitoring_predictions (
289
+ id TEXT PRIMARY KEY,
290
+ prediction_type TEXT NOT NULL,
291
+ component TEXT NOT NULL,
292
+ description TEXT NOT NULL,
293
+ probability REAL NOT NULL,
294
+ estimated_time INTEGER,
295
+ impact TEXT NOT NULL,
296
+ recommendations TEXT,
297
+ confidence REAL NOT NULL,
298
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
299
+ );
300
+ `);
301
+ }
302
+ startRealTimeMonitoring() {
303
+ this.logger.info('🔄 Starting real-time monitoring...');
304
+ this.monitoringInterval = setInterval(async () => {
305
+ try {
306
+ await this.collectSystemMetrics();
307
+ await this.updateSystemHealth();
308
+ // Broadcast to connected clients
309
+ if (this.connectedClients.size > 0) {
310
+ this.broadcastToClients({
311
+ type: 'system_health_update',
312
+ data: this.systemHealth
313
+ });
314
+ }
315
+ }
316
+ catch (error) {
317
+ this.logger.error('❌ Error in real-time monitoring:', error);
318
+ }
319
+ }, 5000); // Every 5 seconds
320
+ }
321
+ startAlertingSystem() {
322
+ this.logger.info('🔔 Starting alerting system...');
323
+ this.alertingInterval = setInterval(async () => {
324
+ try {
325
+ await this.checkAlertConditions();
326
+ await this.cleanupOldAlerts();
327
+ }
328
+ catch (error) {
329
+ this.logger.error('❌ Error in alerting system:', error);
330
+ }
331
+ }, 10000); // Every 10 seconds
332
+ }
333
+ startPredictiveAnalytics() {
334
+ this.logger.info('🔮 Starting predictive analytics...');
335
+ this.predictionInterval = setInterval(async () => {
336
+ try {
337
+ await this.runPredictiveAnalysis();
338
+ }
339
+ catch (error) {
340
+ this.logger.error('❌ Error in predictive analytics:', error);
341
+ }
342
+ }, 300000); // Every 5 minutes
343
+ }
344
+ async startDashboardServer() {
345
+ this.httpServer = http_1.default.createServer((req, res) => {
346
+ this.handleHttpRequest(req, res);
347
+ });
348
+ this.websocketServer = new ws_1.default.Server({
349
+ server: this.httpServer,
350
+ path: '/monitoring-ws'
351
+ });
352
+ this.websocketServer.on('connection', (ws) => {
353
+ this.handleWebSocketConnection(ws);
354
+ });
355
+ return new Promise((resolve) => {
356
+ this.httpServer.listen(this.config.websocketPort, () => {
357
+ this.logger.info(`🌐 Dashboard server started on port ${this.config.websocketPort}`);
358
+ resolve();
359
+ });
360
+ });
361
+ }
362
+ setupPerformanceTrackerIntegration() {
363
+ // Listen to performance tracker events
364
+ this.performanceTracker.on('performance:slow', (data) => {
365
+ this.createAlert('high', 'api', `Slow operation detected: ${data.operation} (${data.duration}ms)`, data);
366
+ });
367
+ this.performanceTracker.on('performance:failure', (data) => {
368
+ this.createAlert('medium', 'api', `Operation failed: ${data.operation} - ${data.error}`, data);
369
+ });
370
+ this.performanceTracker.on('performance:high-memory', (data) => {
371
+ this.createAlert('medium', 'memory', `High memory usage: ${data.operation} (${data.memoryUsage}MB)`, data);
372
+ });
373
+ this.performanceTracker.on('resource:warning', (data) => {
374
+ this.createAlert('high', data.type, `Resource warning: ${data.type} usage at ${(data.usage * 100).toFixed(1)}%`, data);
375
+ });
376
+ }
377
+ async collectSystemMetrics() {
378
+ const timestamp = Date.now();
379
+ // Collect Node.js process metrics
380
+ const memUsage = process.memoryUsage();
381
+ const cpuUsage = process.cpuUsage();
382
+ const metrics = [
383
+ {
384
+ name: 'process_memory_heap_used',
385
+ value: memUsage.heapUsed / 1024 / 1024, // MB
386
+ component: 'memory'
387
+ },
388
+ {
389
+ name: 'process_memory_heap_total',
390
+ value: memUsage.heapTotal / 1024 / 1024, // MB
391
+ component: 'memory'
392
+ },
393
+ {
394
+ name: 'process_memory_rss',
395
+ value: memUsage.rss / 1024 / 1024, // MB
396
+ component: 'memory'
397
+ },
398
+ {
399
+ name: 'process_cpu_user',
400
+ value: cpuUsage.user / 1000, // milliseconds
401
+ component: 'cpu'
402
+ },
403
+ {
404
+ name: 'process_cpu_system',
405
+ value: cpuUsage.system / 1000, // milliseconds
406
+ component: 'cpu'
407
+ }
408
+ ];
409
+ // Collect memory system metrics
410
+ const memoryStats = await this.memory.getDatabaseStats();
411
+ metrics.push({
412
+ name: 'database_size',
413
+ value: memoryStats.size / 1024 / 1024, // MB
414
+ component: 'database'
415
+ });
416
+ // Collect cache metrics if available
417
+ try {
418
+ const cacheStats = await this.memory.getCacheStats();
419
+ metrics.push({
420
+ name: 'cache_hit_rate',
421
+ value: cacheStats.hits / (cacheStats.hits + cacheStats.misses) * 100,
422
+ component: 'cache'
423
+ }, {
424
+ name: 'cache_size',
425
+ value: cacheStats.size,
426
+ component: 'cache'
427
+ });
428
+ }
429
+ catch (error) {
430
+ // Cache stats may not be available
431
+ }
432
+ // Store metrics
433
+ for (const metric of metrics) {
434
+ await this.storeMetric(metric.name, metric.value, metric.component, timestamp);
435
+ // Update history for trend analysis
436
+ const historyKey = `${metric.component}_${metric.name}`;
437
+ if (!this.metricHistory.has(historyKey)) {
438
+ this.metricHistory.set(historyKey, []);
439
+ }
440
+ const history = this.metricHistory.get(historyKey);
441
+ history.push(metric.value);
442
+ // Keep only last 100 values
443
+ if (history.length > 100) {
444
+ history.shift();
445
+ }
446
+ }
447
+ }
448
+ async storeMetric(name, value, component, timestamp) {
449
+ const id = `${component}_${name}_${timestamp}`;
450
+ await this.memory.insert('monitoring_metrics', {
451
+ id,
452
+ metric_name: name,
453
+ metric_value: value,
454
+ component,
455
+ timestamp,
456
+ metadata: JSON.stringify({
457
+ node_version: process.version,
458
+ platform: process.platform,
459
+ arch: process.arch
460
+ })
461
+ });
462
+ }
463
+ async updateSystemHealth() {
464
+ const now = new Date();
465
+ // Update CPU health
466
+ const cpuHistory = this.metricHistory.get('cpu_process_cpu_user') || [];
467
+ if (cpuHistory.length > 0) {
468
+ const currentCpu = cpuHistory[cpuHistory.length - 1] || 0;
469
+ this.systemHealth.components.cpu = {
470
+ status: currentCpu > this.config.alertThresholds.cpuUsage ? 'critical' :
471
+ currentCpu > this.config.alertThresholds.cpuUsage * 0.8 ? 'warning' : 'healthy',
472
+ value: currentCpu,
473
+ threshold: this.config.alertThresholds.cpuUsage,
474
+ trend: this.calculateTrend('cpu', cpuHistory),
475
+ lastUpdated: now,
476
+ details: `CPU usage: ${currentCpu.toFixed(1)}%`
477
+ };
478
+ }
479
+ // Update Memory health
480
+ const memHistory = this.metricHistory.get('memory_process_memory_heap_used') || [];
481
+ if (memHistory.length > 0) {
482
+ const currentMem = memHistory[memHistory.length - 1] || 0;
483
+ this.systemHealth.components.memory = {
484
+ status: currentMem > 500 ? 'critical' : currentMem > 300 ? 'warning' : 'healthy',
485
+ value: currentMem,
486
+ threshold: 500,
487
+ trend: this.calculateTrend('memory', memHistory),
488
+ lastUpdated: now,
489
+ details: `Heap usage: ${currentMem.toFixed(1)}MB`
490
+ };
491
+ }
492
+ // Update Database health
493
+ const dbHistory = this.metricHistory.get('database_database_size') || [];
494
+ if (dbHistory.length > 0) {
495
+ const currentDb = dbHistory[dbHistory.length - 1] || 0;
496
+ this.systemHealth.components.database = {
497
+ status: currentDb > 1000 ? 'warning' : 'healthy',
498
+ value: currentDb,
499
+ threshold: 1000,
500
+ trend: this.calculateTrend('database', dbHistory),
501
+ lastUpdated: now,
502
+ details: `Database size: ${currentDb.toFixed(1)}MB`
503
+ };
504
+ }
505
+ // Update Cache health
506
+ const cacheHitHistory = this.metricHistory.get('cache_cache_hit_rate') || [];
507
+ if (cacheHitHistory.length > 0) {
508
+ const currentHitRate = cacheHitHistory[cacheHitHistory.length - 1] || 0;
509
+ this.systemHealth.components.cache = {
510
+ status: currentHitRate < this.config.alertThresholds.cacheHitRate ? 'warning' : 'healthy',
511
+ value: currentHitRate,
512
+ threshold: this.config.alertThresholds.cacheHitRate,
513
+ trend: this.calculateTrend('cache', cacheHitHistory),
514
+ lastUpdated: now,
515
+ details: `Cache hit rate: ${currentHitRate.toFixed(1)}%`
516
+ };
517
+ }
518
+ // Calculate overall health
519
+ const componentStatuses = Object.values(this.systemHealth.components).map(c => c.status);
520
+ if (componentStatuses.includes('critical')) {
521
+ this.systemHealth.overall = 'critical';
522
+ }
523
+ else if (componentStatuses.includes('warning')) {
524
+ this.systemHealth.overall = 'warning';
525
+ }
526
+ else if (componentStatuses.every(s => s === 'healthy')) {
527
+ this.systemHealth.overall = 'healthy';
528
+ }
529
+ else {
530
+ this.systemHealth.overall = 'unknown';
531
+ }
532
+ // Update alerts list
533
+ this.systemHealth.alerts = await this.getActiveAlerts();
534
+ }
535
+ calculateTrend(component, history) {
536
+ if (history.length < 10)
537
+ return 'stable';
538
+ const recent = history.slice(-5);
539
+ const older = history.slice(-10, -5);
540
+ const recentAvg = recent.reduce((a, b) => a + b, 0) / recent.length;
541
+ const olderAvg = older.reduce((a, b) => a + b, 0) / older.length;
542
+ const changePercent = ((recentAvg - olderAvg) / olderAvg) * 100;
543
+ // For CPU, memory, response time: increasing is degrading
544
+ // For cache hit rate, throughput: increasing is improving
545
+ const isInverseMetric = component.includes('cache') || component.includes('throughput');
546
+ if (Math.abs(changePercent) < 5)
547
+ return 'stable';
548
+ if (isInverseMetric) {
549
+ return changePercent > 0 ? 'improving' : 'degrading';
550
+ }
551
+ else {
552
+ return changePercent > 0 ? 'degrading' : 'improving';
553
+ }
554
+ }
555
+ async checkAlertConditions() {
556
+ const now = Date.now();
557
+ // Check each component health
558
+ for (const [componentName, component] of Object.entries(this.systemHealth.components)) {
559
+ if (component.status === 'critical' || component.status === 'warning') {
560
+ const severity = component.status === 'critical' ? 'critical' : 'high';
561
+ const alertId = `${componentName}_${component.status}`;
562
+ if (this.activeAlerts.has(alertId)) {
563
+ // Update existing alert
564
+ const alert = this.activeAlerts.get(alertId);
565
+ alert.count++;
566
+ alert.lastSeen = new Date();
567
+ }
568
+ else {
569
+ // Create new alert
570
+ await this.createAlert(severity, componentName, component.details, {
571
+ threshold: component.threshold,
572
+ currentValue: component.value,
573
+ trend: component.trend
574
+ });
575
+ }
576
+ }
577
+ }
578
+ }
579
+ async createAlert(severity, component, message, metadata) {
580
+ const alertId = `${component}_${severity}_${Date.now()}`;
581
+ const now = new Date();
582
+ const alert = {
583
+ id: alertId,
584
+ severity,
585
+ component,
586
+ message,
587
+ timestamp: now,
588
+ acknowledged: false,
589
+ count: 1,
590
+ firstSeen: now
591
+ };
592
+ this.activeAlerts.set(alertId, alert);
593
+ // Store in database
594
+ await this.memory.insert('monitoring_alerts', {
595
+ id: alertId,
596
+ severity,
597
+ component,
598
+ message,
599
+ timestamp: now.getTime(),
600
+ acknowledged: false,
601
+ count: 1,
602
+ first_seen: now.getTime(),
603
+ last_seen: now.getTime(),
604
+ metadata: JSON.stringify(metadata || {})
605
+ });
606
+ this.logger.warn(`🚨 Alert created: ${severity.toUpperCase()} - ${component} - ${message}`, { alertId });
607
+ // Emit alert event
608
+ this.emit('alert', alert);
609
+ // Broadcast to connected clients
610
+ this.broadcastToClients({
611
+ type: 'new_alert',
612
+ data: alert
613
+ });
614
+ }
615
+ async cleanupOldAlerts() {
616
+ const cutoff = Date.now() - (24 * 60 * 60 * 1000); // 24 hours
617
+ for (const [alertId, alert] of this.activeAlerts) {
618
+ if (alert.timestamp.getTime() < cutoff && alert.acknowledged) {
619
+ this.activeAlerts.delete(alertId);
620
+ }
621
+ }
622
+ }
623
+ async runPredictiveAnalysis() {
624
+ this.logger.debug('🔮 Running predictive analysis...');
625
+ const predictions = [];
626
+ // Analyze memory growth
627
+ const memHistory = this.metricHistory.get('memory_process_memory_heap_used') || [];
628
+ if (memHistory.length > 20) {
629
+ const memoryPrediction = this.predictResourceExhaustion('memory', memHistory, 1000); // 1GB limit
630
+ if (memoryPrediction) {
631
+ predictions.push(memoryPrediction);
632
+ }
633
+ }
634
+ // Analyze database growth
635
+ const dbHistory = this.metricHistory.get('database_database_size') || [];
636
+ if (dbHistory.length > 20) {
637
+ const dbPrediction = this.predictResourceExhaustion('database', dbHistory, 5000); // 5GB limit
638
+ if (dbPrediction) {
639
+ predictions.push(dbPrediction);
640
+ }
641
+ }
642
+ // Store predictions
643
+ for (const prediction of predictions) {
644
+ await this.memory.insert('monitoring_predictions', {
645
+ id: `prediction_${prediction.type}_${prediction.component}_${Date.now()}`,
646
+ prediction_type: prediction.type,
647
+ component: prediction.component,
648
+ description: prediction.description,
649
+ probability: prediction.probability,
650
+ estimated_time: prediction.estimatedTime?.getTime(),
651
+ impact: prediction.impact,
652
+ recommendations: JSON.stringify(prediction.recommendations),
653
+ confidence: prediction.probability
654
+ });
655
+ }
656
+ // Update system health with predictions
657
+ this.systemHealth.predictedIssues = predictions;
658
+ }
659
+ predictResourceExhaustion(resource, history, limit) {
660
+ if (history.length < 10)
661
+ return null;
662
+ // Simple linear regression to predict growth
663
+ const recentHistory = history.slice(-20);
664
+ const n = recentHistory.length;
665
+ const x = Array.from({ length: n }, (_, i) => i);
666
+ const y = recentHistory;
667
+ const sumX = x.reduce((a, b) => a + b, 0);
668
+ const sumY = y.reduce((a, b) => a + b, 0);
669
+ const sumXY = x.reduce((sum, xi, i) => sum + xi * y[i], 0);
670
+ const sumXX = x.reduce((sum, xi) => sum + xi * xi, 0);
671
+ const slope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX);
672
+ const intercept = (sumY - slope * sumX) / n;
673
+ // Predict when resource will reach limit
674
+ if (slope > 0) {
675
+ const currentValue = y[y.length - 1];
676
+ const timeToLimit = (limit - currentValue) / slope;
677
+ if (timeToLimit > 0 && timeToLimit < 1000) { // Within 1000 time units
678
+ const probability = Math.min(0.9, Math.max(0.1, 1 - (timeToLimit / 1000)));
679
+ const estimatedTime = new Date(Date.now() + (timeToLimit * 300000)); // 5-minute intervals
680
+ return {
681
+ type: 'resource_exhaustion',
682
+ component: resource,
683
+ description: `${resource} usage is growing and may reach capacity limits`,
684
+ probability,
685
+ estimatedTime,
686
+ impact: timeToLimit < 100 ? 'critical' : timeToLimit < 300 ? 'high' : 'medium',
687
+ recommendations: [
688
+ `Monitor ${resource} usage closely`,
689
+ `Consider optimizing ${resource} consumption`,
690
+ 'Implement cleanup/archival processes',
691
+ 'Scale resources if necessary'
692
+ ]
693
+ };
694
+ }
695
+ }
696
+ return null;
697
+ }
698
+ async calculateTrend(metric, period) {
699
+ const timeframe = {
700
+ hour: 3600000,
701
+ day: 86400000,
702
+ week: 604800000
703
+ }[period];
704
+ const since = Date.now() - timeframe;
705
+ const metrics = await this.memory.query(`
706
+ SELECT metric_value, timestamp FROM monitoring_metrics
707
+ WHERE metric_name = ? AND timestamp > ?
708
+ ORDER BY timestamp
709
+ `, [metric, since]);
710
+ if (metrics.length < 10)
711
+ return null;
712
+ const values = metrics.map(m => m.metric_value);
713
+ const recent = values.slice(-Math.floor(values.length / 3));
714
+ const older = values.slice(0, Math.floor(values.length / 3));
715
+ const recentAvg = recent.reduce((a, b) => a + b, 0) / recent.length;
716
+ const olderAvg = older.reduce((a, b) => a + b, 0) / older.length;
717
+ const overallAvg = values.reduce((a, b) => a + b, 0) / values.length;
718
+ const percentageChange = ((recentAvg - olderAvg) / olderAvg) * 100;
719
+ const variance = values.reduce((sum, val) => sum + Math.pow(val - overallAvg, 2), 0) / values.length;
720
+ const volatility = Math.sqrt(variance) / overallAvg;
721
+ return {
722
+ metric,
723
+ period,
724
+ trend: Math.abs(percentageChange) < 5 ? 'stable' :
725
+ percentageChange > 0 ? 'degrading' : 'improving',
726
+ percentageChange,
727
+ currentValue: recentAvg,
728
+ historicalAverage: overallAvg,
729
+ volatility
730
+ };
731
+ }
732
+ async generateResourceForecast(resource, timeHorizonHours) {
733
+ const history = this.metricHistory.get(`${resource}_${resource}_usage`) ||
734
+ this.metricHistory.get(`${resource}_process_memory_heap_used`) ||
735
+ this.metricHistory.get(`${resource}_database_size`) || [];
736
+ if (history.length < 10)
737
+ return null;
738
+ const currentUsage = history[history.length - 1] || 0;
739
+ const trend = this.calculateTrend(resource, history);
740
+ // Simple prediction based on trend
741
+ let predictedUsage = currentUsage;
742
+ let confidence = 0.5;
743
+ if (trend === 'degrading') {
744
+ const growthRate = this.calculateGrowthRate(history);
745
+ predictedUsage = currentUsage * (1 + (growthRate * timeHorizonHours / 24));
746
+ confidence = 0.7;
747
+ }
748
+ else if (trend === 'improving') {
749
+ const reductionRate = this.calculateGrowthRate(history);
750
+ predictedUsage = currentUsage * (1 + (reductionRate * timeHorizonHours / 24));
751
+ confidence = 0.6;
752
+ }
753
+ const recommendations = [];
754
+ let exhaustionDate;
755
+ if (predictedUsage > currentUsage * 1.5) {
756
+ recommendations.push(`${resource} usage expected to increase significantly`);
757
+ recommendations.push('Consider implementing resource optimization');
758
+ }
759
+ if (predictedUsage > 1000) { // Arbitrary threshold
760
+ exhaustionDate = new Date(Date.now() + (timeHorizonHours * 3600000));
761
+ recommendations.push('Resource exhaustion predicted - immediate action required');
762
+ }
763
+ return {
764
+ resource,
765
+ currentUsage,
766
+ predictedUsage,
767
+ timeHorizon: timeHorizonHours,
768
+ confidence,
769
+ exhaustionDate,
770
+ recommendations
771
+ };
772
+ }
773
+ calculateGrowthRate(history) {
774
+ if (history.length < 5)
775
+ return 0;
776
+ const recent = history.slice(-5);
777
+ const older = history.slice(-10, -5);
778
+ const recentAvg = recent.reduce((a, b) => a + b) / recent.length;
779
+ const olderAvg = older.reduce((a, b) => a + b) / older.length;
780
+ return (recentAvg - olderAvg) / olderAvg;
781
+ }
782
+ calculatePerformanceScore(performanceReport, systemHealth) {
783
+ let score = 100;
784
+ // Deduct points for errors
785
+ score -= performanceReport.summary.errorRate * 2;
786
+ // Deduct points for slow response times
787
+ if (performanceReport.summary.averageResponseTime > 2000) {
788
+ score -= (performanceReport.summary.averageResponseTime - 2000) / 100;
789
+ }
790
+ // Deduct points for unhealthy components
791
+ const unhealthyComponents = Object.values(systemHealth.components)
792
+ .filter(c => c.status !== 'healthy').length;
793
+ score -= unhealthyComponents * 10;
794
+ // Deduct points for critical alerts
795
+ const criticalAlerts = systemHealth.alerts.filter(a => a.severity === 'critical').length;
796
+ score -= criticalAlerts * 15;
797
+ return Math.max(0, Math.min(100, score));
798
+ }
799
+ async generateSmartRecommendations() {
800
+ const recommendations = [];
801
+ // Analyze system health and generate recommendations
802
+ for (const [componentName, component] of Object.entries(this.systemHealth.components)) {
803
+ if (component.status !== 'healthy') {
804
+ if (componentName === 'memory' && component.trend === 'degrading') {
805
+ recommendations.push('Consider implementing memory optimization strategies');
806
+ recommendations.push('Review memory leaks in long-running processes');
807
+ }
808
+ if (componentName === 'cpu' && component.value > 80) {
809
+ recommendations.push('CPU usage is high - consider scaling or optimization');
810
+ }
811
+ if (componentName === 'cache' && component.value < 50) {
812
+ recommendations.push('Cache hit rate is low - review caching strategy');
813
+ }
814
+ }
815
+ }
816
+ // Add predictive recommendations
817
+ for (const prediction of this.systemHealth.predictedIssues) {
818
+ recommendations.push(...prediction.recommendations);
819
+ }
820
+ return [...new Set(recommendations)]; // Remove duplicates
821
+ }
822
+ async getDataPointCount(period) {
823
+ const timeframe = {
824
+ hour: 3600000,
825
+ day: 86400000,
826
+ week: 604800000,
827
+ month: 2592000000
828
+ }[period] || 86400000;
829
+ const since = Date.now() - timeframe;
830
+ const result = await this.memory.query(`
831
+ SELECT COUNT(*) as count FROM monitoring_metrics
832
+ WHERE timestamp > ?
833
+ `, [since]);
834
+ return result[0]?.count || 0;
835
+ }
836
+ handleWebSocketConnection(ws) {
837
+ this.connectedClients.add(ws);
838
+ this.logger.info('📱 WebSocket client connected', { totalClients: this.connectedClients.size });
839
+ // Send initial system health
840
+ ws.send(JSON.stringify({
841
+ type: 'initial_data',
842
+ data: {
843
+ systemHealth: this.systemHealth,
844
+ timestamp: new Date()
845
+ }
846
+ }));
847
+ ws.on('close', () => {
848
+ this.connectedClients.delete(ws);
849
+ this.logger.info('📱 WebSocket client disconnected', { totalClients: this.connectedClients.size });
850
+ });
851
+ ws.on('message', async (message) => {
852
+ try {
853
+ const data = JSON.parse(message.toString());
854
+ await this.handleWebSocketMessage(ws, data);
855
+ }
856
+ catch (error) {
857
+ this.logger.error('❌ Error handling WebSocket message:', error);
858
+ }
859
+ });
860
+ }
861
+ async handleWebSocketMessage(ws, message) {
862
+ switch (message.type) {
863
+ case 'acknowledge_alert':
864
+ if (message.alertId && message.user) {
865
+ const success = await this.acknowledgeAlert(message.alertId, message.user);
866
+ ws.send(JSON.stringify({
867
+ type: 'alert_acknowledged',
868
+ success,
869
+ alertId: message.alertId
870
+ }));
871
+ }
872
+ break;
873
+ case 'get_performance_trends':
874
+ const trends = await this.getPerformanceTrends(message.periods || ['day']);
875
+ ws.send(JSON.stringify({
876
+ type: 'performance_trends',
877
+ data: trends
878
+ }));
879
+ break;
880
+ case 'get_resource_forecasts':
881
+ const forecasts = await this.getResourceForecasts(message.timeHorizon || 24);
882
+ ws.send(JSON.stringify({
883
+ type: 'resource_forecasts',
884
+ data: forecasts
885
+ }));
886
+ break;
887
+ }
888
+ }
889
+ handleHttpRequest(req, res) {
890
+ // Serve basic monitoring dashboard
891
+ const dashboardHtml = this.generateDashboardHtml();
892
+ res.writeHead(200, {
893
+ 'Content-Type': 'text/html',
894
+ 'Content-Length': Buffer.byteLength(dashboardHtml)
895
+ });
896
+ res.end(dashboardHtml);
897
+ }
898
+ generateDashboardHtml() {
899
+ return `
900
+ <!DOCTYPE html>
901
+ <html>
902
+ <head>
903
+ <title>Snow-Flow Enhanced Monitoring Dashboard</title>
904
+ <style>
905
+ body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; }
906
+ .header { background: #2c3e50; color: white; padding: 20px; border-radius: 5px; margin-bottom: 20px; }
907
+ .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; }
908
+ .card { background: white; padding: 20px; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
909
+ .status-healthy { color: #27ae60; }
910
+ .status-warning { color: #f39c12; }
911
+ .status-critical { color: #e74c3c; }
912
+ .status-unknown { color: #95a5a6; }
913
+ .metric { display: flex; justify-content: space-between; margin: 10px 0; }
914
+ .alert { padding: 10px; margin: 5px 0; border-radius: 3px; }
915
+ .alert-critical { background: #ffebee; border-left: 4px solid #e74c3c; }
916
+ .alert-high { background: #fff3e0; border-left: 4px solid #ff9800; }
917
+ .alert-medium { background: #f3e5f5; border-left: 4px solid #9c27b0; }
918
+ .alert-low { background: #e8f5e8; border-left: 4px solid #4caf50; }
919
+ #connectionStatus { position: fixed; top: 10px; right: 10px; padding: 5px 10px; border-radius: 3px; }
920
+ .connected { background: #4caf50; color: white; }
921
+ .disconnected { background: #f44336; color: white; }
922
+ </style>
923
+ </head>
924
+ <body>
925
+ <div class="header">
926
+ <h1>🚀 Snow-Flow Enhanced Monitoring Dashboard</h1>
927
+ <p>Real-time system health and performance monitoring</p>
928
+ <div id="connectionStatus" class="disconnected">Connecting...</div>
929
+ </div>
930
+
931
+ <div class="grid">
932
+ <div class="card">
933
+ <h3>System Health Overview</h3>
934
+ <div id="overallHealth">Loading...</div>
935
+ <div id="componentHealth"></div>
936
+ </div>
937
+
938
+ <div class="card">
939
+ <h3>Active Alerts</h3>
940
+ <div id="alerts">Loading...</div>
941
+ </div>
942
+
943
+ <div class="card">
944
+ <h3>Performance Metrics</h3>
945
+ <div id="performanceMetrics">Loading...</div>
946
+ </div>
947
+
948
+ <div class="card">
949
+ <h3>Resource Usage</h3>
950
+ <div id="resourceUsage">Loading...</div>
951
+ </div>
952
+ </div>
953
+
954
+ <script>
955
+ const ws = new WebSocket('ws://localhost:${this.config.websocketPort}/monitoring-ws');
956
+ const connectionStatus = document.getElementById('connectionStatus');
957
+
958
+ ws.onopen = function() {
959
+ connectionStatus.textContent = 'Connected';
960
+ connectionStatus.className = 'connected';
961
+ };
962
+
963
+ ws.onclose = function() {
964
+ connectionStatus.textContent = 'Disconnected';
965
+ connectionStatus.className = 'disconnected';
966
+ };
967
+
968
+ ws.onmessage = function(event) {
969
+ const message = JSON.parse(event.data);
970
+
971
+ switch(message.type) {
972
+ case 'initial_data':
973
+ case 'system_health_update':
974
+ updateSystemHealth(message.data.systemHealth || message.data);
975
+ break;
976
+ case 'new_alert':
977
+ addAlert(message.data);
978
+ break;
979
+ }
980
+ };
981
+
982
+ function updateSystemHealth(health) {
983
+ // Update overall health
984
+ const overallHealth = document.getElementById('overallHealth');
985
+ overallHealth.innerHTML = \`
986
+ <div class="metric">
987
+ <span>Overall Status:</span>
988
+ <span class="status-\${health.overall}">\${health.overall.toUpperCase()}</span>
989
+ </div>
990
+ \`;
991
+
992
+ // Update component health
993
+ const componentHealth = document.getElementById('componentHealth');
994
+ let componentsHtml = '';
995
+
996
+ for (const [name, component] of Object.entries(health.components)) {
997
+ componentsHtml += \`
998
+ <div class="metric">
999
+ <span>\${name.charAt(0).toUpperCase() + name.slice(1)}:</span>
1000
+ <span class="status-\${component.status}">
1001
+ \${component.value.toFixed(1)} (\${component.status})
1002
+ </span>
1003
+ </div>
1004
+ \`;
1005
+ }
1006
+ componentHealth.innerHTML = componentsHtml;
1007
+
1008
+ // Update alerts
1009
+ updateAlerts(health.alerts || []);
1010
+ }
1011
+
1012
+ function updateAlerts(alerts) {
1013
+ const alertsDiv = document.getElementById('alerts');
1014
+
1015
+ if (alerts.length === 0) {
1016
+ alertsDiv.innerHTML = '<p>No active alerts</p>';
1017
+ return;
1018
+ }
1019
+
1020
+ let alertsHtml = '';
1021
+ alerts.slice(0, 10).forEach(alert => {
1022
+ alertsHtml += \`
1023
+ <div class="alert alert-\${alert.severity}">
1024
+ <strong>\${alert.component.toUpperCase()}</strong>: \${alert.message}
1025
+ <br><small>\${new Date(alert.timestamp).toLocaleString()}</small>
1026
+ </div>
1027
+ \`;
1028
+ });
1029
+
1030
+ alertsDiv.innerHTML = alertsHtml;
1031
+ }
1032
+
1033
+ function addAlert(alert) {
1034
+ // Add new alert to the top of the list
1035
+ const alertsDiv = document.getElementById('alerts');
1036
+ const newAlertHtml = \`
1037
+ <div class="alert alert-\${alert.severity}">
1038
+ <strong>\${alert.component.toUpperCase()}</strong>: \${alert.message}
1039
+ <br><small>\${new Date(alert.timestamp).toLocaleString()}</small>
1040
+ </div>
1041
+ \`;
1042
+
1043
+ alertsDiv.innerHTML = newAlertHtml + alertsDiv.innerHTML;
1044
+ }
1045
+ </script>
1046
+ </body>
1047
+ </html>
1048
+ `;
1049
+ }
1050
+ broadcastToClients(message) {
1051
+ const messageStr = JSON.stringify(message);
1052
+ this.connectedClients.forEach(client => {
1053
+ if (client.readyState === ws_1.default.OPEN) {
1054
+ client.send(messageStr);
1055
+ }
1056
+ });
1057
+ }
1058
+ /**
1059
+ * Shutdown the monitoring system
1060
+ */
1061
+ async shutdown() {
1062
+ this.logger.info('🛑 Shutting down Enhanced Monitoring System...');
1063
+ // Clear intervals
1064
+ if (this.monitoringInterval)
1065
+ clearInterval(this.monitoringInterval);
1066
+ if (this.alertingInterval)
1067
+ clearInterval(this.alertingInterval);
1068
+ if (this.predictionInterval)
1069
+ clearInterval(this.predictionInterval);
1070
+ // Close WebSocket connections
1071
+ this.connectedClients.forEach(client => {
1072
+ client.close();
1073
+ });
1074
+ this.connectedClients.clear();
1075
+ // Close servers
1076
+ if (this.websocketServer) {
1077
+ this.websocketServer.close();
1078
+ }
1079
+ if (this.httpServer) {
1080
+ this.httpServer.close();
1081
+ }
1082
+ this.logger.info('✅ Enhanced Monitoring System shut down');
1083
+ }
1084
+ }
1085
+ exports.EnhancedMonitoringSystem = EnhancedMonitoringSystem;