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