claude-flow-novice 1.5.3 → 1.5.5

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.
@@ -0,0 +1,339 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * SDK Migration Monitoring Script
5
+ * Provides real-time monitoring and alerting during migration
6
+ */
7
+
8
+ const { MetricsCollector, SDKDashboard } = require('../src/sdk/dashboard');
9
+ const { defaultConfig } = require('../src/sdk/performance-config');
10
+ const fs = require('fs').promises;
11
+ const path = require('path');
12
+
13
+ class MigrationMonitor {
14
+ constructor(config = {}) {
15
+ this.config = {
16
+ checkInterval: config.checkInterval || 60000, // 1 minute
17
+ alertThresholds: {
18
+ errorRate: 0.05,
19
+ validationFailureRate: 0.2,
20
+ responseTimeP95: 10000,
21
+ cacheHitRate: 0.3
22
+ },
23
+ ...config
24
+ };
25
+
26
+ this.collector = new MetricsCollector();
27
+ this.dashboard = new SDKDashboard(this.collector, {
28
+ port: config.dashboardPort || 3000,
29
+ updateInterval: 5000,
30
+ authentication: false
31
+ });
32
+
33
+ this.alerts = [];
34
+ this.metricsHistory = [];
35
+ this.isMonitoring = false;
36
+ }
37
+
38
+ async start() {
39
+ console.log('šŸš€ Starting SDK Migration Monitor...\n');
40
+
41
+ // Start dashboard
42
+ this.dashboard.start(() => {
43
+ console.log('āœ… Dashboard started successfully\n');
44
+ });
45
+
46
+ // Start metrics collection
47
+ this.isMonitoring = true;
48
+ this.startMetricsCollection();
49
+
50
+ // Set up graceful shutdown
51
+ process.on('SIGINT', () => this.stop());
52
+ process.on('SIGTERM', () => this.stop());
53
+ }
54
+
55
+ async stop() {
56
+ console.log('\nšŸ›‘ Stopping migration monitor...');
57
+ this.isMonitoring = false;
58
+
59
+ // Save final metrics
60
+ await this.saveMetricsSnapshot();
61
+
62
+ // Stop dashboard
63
+ this.dashboard.stop();
64
+
65
+ console.log('āœ… Monitor stopped');
66
+ process.exit(0);
67
+ }
68
+
69
+ startMetricsCollection() {
70
+ // Simulate metrics collection (replace with actual implementation)
71
+ const collectMetrics = async () => {
72
+ if (!this.isMonitoring) return;
73
+
74
+ try {
75
+ // Collect system metrics
76
+ const systemMetrics = await this.collectSystemMetrics();
77
+ this.recordSystemMetrics(systemMetrics);
78
+
79
+ // Collect application metrics
80
+ const appMetrics = await this.collectApplicationMetrics();
81
+ this.recordApplicationMetrics(appMetrics);
82
+
83
+ // Check thresholds and trigger alerts
84
+ await this.checkThresholds();
85
+
86
+ // Store metrics history
87
+ this.metricsHistory.push({
88
+ timestamp: Date.now(),
89
+ system: systemMetrics,
90
+ application: appMetrics
91
+ });
92
+
93
+ // Keep only last 1000 entries
94
+ if (this.metricsHistory.length > 1000) {
95
+ this.metricsHistory = this.metricsHistory.slice(-1000);
96
+ }
97
+
98
+ // Save snapshot periodically
99
+ if (this.metricsHistory.length % 10 === 0) {
100
+ await this.saveMetricsSnapshot();
101
+ }
102
+ } catch (error) {
103
+ console.error('Error collecting metrics:', error);
104
+ }
105
+
106
+ // Schedule next collection
107
+ setTimeout(collectMetrics, this.config.checkInterval);
108
+ };
109
+
110
+ collectMetrics();
111
+ }
112
+
113
+ async collectSystemMetrics() {
114
+ const os = require('os');
115
+
116
+ return {
117
+ cpu: this.getCPUUsage(),
118
+ memory: (1 - os.freemem() / os.totalmem()) * 100,
119
+ loadAverage: os.loadavg()[0],
120
+ uptime: os.uptime()
121
+ };
122
+ }
123
+
124
+ getCPUUsage() {
125
+ const cpus = require('os').cpus();
126
+ const totalIdle = cpus.reduce((acc, cpu) => acc + cpu.times.idle, 0);
127
+ const totalTick = cpus.reduce(
128
+ (acc, cpu) => acc + Object.values(cpu.times).reduce((a, b) => a + b, 0),
129
+ 0
130
+ );
131
+ return ((1 - totalIdle / totalTick) * 100);
132
+ }
133
+
134
+ async collectApplicationMetrics() {
135
+ // In real implementation, collect from actual application
136
+ // For now, generate simulated metrics
137
+ return {
138
+ responseTime: Math.random() * 1000 + 200,
139
+ throughput: Math.floor(Math.random() * 100) + 50,
140
+ errorRate: Math.random() * 0.02,
141
+ cacheHitRate: 0.6 + Math.random() * 0.3,
142
+ validationSuccess: 0.9 + Math.random() * 0.09,
143
+ testPassRate: 0.95 + Math.random() * 0.04,
144
+ coverage: 80 + Math.random() * 15,
145
+ activeAgents: Math.floor(Math.random() * 5) + 2,
146
+ queuedTasks: Math.floor(Math.random() * 10)
147
+ };
148
+ }
149
+
150
+ recordSystemMetrics(metrics) {
151
+ this.collector.recordMetric('system', 'cpuUsage', metrics.cpu);
152
+ this.collector.recordMetric('system', 'memoryUsage', metrics.memory);
153
+ this.collector.recordMetric('system', 'activeAgents', metrics.activeAgents || 0);
154
+ this.collector.recordMetric('system', 'queuedTasks', metrics.queuedTasks || 0);
155
+ }
156
+
157
+ recordApplicationMetrics(metrics) {
158
+ this.collector.recordMetric('performance', 'responseTime', metrics.responseTime);
159
+ this.collector.recordMetric('performance', 'throughput', metrics.throughput);
160
+ this.collector.recordMetric('performance', 'errorRate', metrics.errorRate);
161
+ this.collector.recordMetric('performance', 'cacheHitRate', metrics.cacheHitRate);
162
+
163
+ this.collector.recordMetric('quality', 'validationSuccess', metrics.validationSuccess);
164
+ this.collector.recordMetric('quality', 'testPassRate', metrics.testPassRate);
165
+ this.collector.recordMetric('quality', 'coverageMetrics', metrics.coverage);
166
+
167
+ // Estimate token usage and cost
168
+ const estimatedTokens = metrics.throughput * 1000; // ~1k tokens per request
169
+ this.collector.recordMetric('cost', 'tokenUsage', estimatedTokens);
170
+ this.collector.metrics.cost.estimatedCost += estimatedTokens * 0.000003; // $3 per 1M tokens
171
+ }
172
+
173
+ async checkThresholds() {
174
+ const summary = this.collector.getSummary();
175
+
176
+ // Check error rate
177
+ if (summary.performance.errorRate > this.config.alertThresholds.errorRate) {
178
+ this.triggerAlert({
179
+ id: `error-rate-${Date.now()}`,
180
+ name: 'high-error-rate',
181
+ severity: 'critical',
182
+ message: `Error rate ${(summary.performance.errorRate * 100).toFixed(2)}% exceeds threshold ${(this.config.alertThresholds.errorRate * 100).toFixed(2)}%`,
183
+ metric: 'errorRate',
184
+ currentValue: summary.performance.errorRate,
185
+ threshold: this.config.alertThresholds.errorRate,
186
+ recommendation: 'Consider rolling back migration'
187
+ });
188
+ }
189
+
190
+ // Check validation failure rate
191
+ const validationFailureRate = 1 - summary.quality.validationSuccessRate;
192
+ if (validationFailureRate > this.config.alertThresholds.validationFailureRate) {
193
+ this.triggerAlert({
194
+ id: `validation-failure-${Date.now()}`,
195
+ name: 'validation-failure-spike',
196
+ severity: 'high',
197
+ message: `Validation failure rate ${(validationFailureRate * 100).toFixed(2)}% exceeds threshold`,
198
+ metric: 'validationFailureRate',
199
+ currentValue: validationFailureRate,
200
+ threshold: this.config.alertThresholds.validationFailureRate,
201
+ recommendation: 'Review validation configuration'
202
+ });
203
+ }
204
+
205
+ // Check response time
206
+ if (summary.performance.responseTime.p95 > this.config.alertThresholds.responseTimeP95) {
207
+ this.triggerAlert({
208
+ id: `slow-response-${Date.now()}`,
209
+ name: 'slow-response-time',
210
+ severity: 'warning',
211
+ message: `P95 response time ${summary.performance.responseTime.p95.toFixed(0)}ms exceeds threshold`,
212
+ metric: 'responseTimeP95',
213
+ currentValue: summary.performance.responseTime.p95,
214
+ threshold: this.config.alertThresholds.responseTimeP95,
215
+ recommendation: 'Check for performance bottlenecks'
216
+ });
217
+ }
218
+
219
+ // Check cache hit rate
220
+ if (summary.performance.cacheHitRate < this.config.alertThresholds.cacheHitRate) {
221
+ this.triggerAlert({
222
+ id: `low-cache-${Date.now()}`,
223
+ name: 'low-cache-hit-rate',
224
+ severity: 'warning',
225
+ message: `Cache hit rate ${(summary.performance.cacheHitRate * 100).toFixed(1)}% below threshold`,
226
+ metric: 'cacheHitRate',
227
+ currentValue: summary.performance.cacheHitRate,
228
+ threshold: this.config.alertThresholds.cacheHitRate,
229
+ recommendation: 'Review cache configuration'
230
+ });
231
+ }
232
+ }
233
+
234
+ triggerAlert(alert) {
235
+ // Deduplicate alerts (don't trigger same alert multiple times)
236
+ const existingAlert = this.alerts.find(
237
+ a => a.name === alert.name && !a.resolved && Date.now() - a.timestamp < 300000
238
+ );
239
+
240
+ if (existingAlert) return;
241
+
242
+ // Add to collector
243
+ this.collector.addAlert(alert);
244
+ this.alerts.push(alert);
245
+
246
+ // Print to console
247
+ const icon = alert.severity === 'critical' ? '🚨' : alert.severity === 'high' ? 'āš ļø' : '⚔';
248
+ console.log(`\n${icon} ALERT: ${alert.name}`);
249
+ console.log(` ${alert.message}`);
250
+ console.log(` Recommendation: ${alert.recommendation}\n`);
251
+
252
+ // Write to file
253
+ this.saveAlert(alert);
254
+ }
255
+
256
+ async saveAlert(alert) {
257
+ const alertsFile = path.join(__dirname, '../logs/alerts.json');
258
+
259
+ try {
260
+ let alerts = [];
261
+ try {
262
+ const content = await fs.readFile(alertsFile, 'utf8');
263
+ alerts = JSON.parse(content);
264
+ } catch (err) {
265
+ // File doesn't exist yet
266
+ }
267
+
268
+ alerts.push(alert);
269
+
270
+ await fs.writeFile(alertsFile, JSON.stringify(alerts, null, 2));
271
+ } catch (error) {
272
+ console.error('Error saving alert:', error);
273
+ }
274
+ }
275
+
276
+ async saveMetricsSnapshot() {
277
+ const summary = this.collector.getSummary();
278
+ const snapshotFile = path.join(__dirname, '../.metrics-snapshot');
279
+
280
+ try {
281
+ await fs.writeFile(snapshotFile, JSON.stringify(summary, null, 2));
282
+ } catch (error) {
283
+ console.error('Error saving metrics snapshot:', error);
284
+ }
285
+ }
286
+
287
+ generateReport() {
288
+ const summary = this.collector.getSummary();
289
+
290
+ console.log('\n' + '='.repeat(80));
291
+ console.log('SDK MIGRATION MONITORING REPORT');
292
+ console.log('='.repeat(80));
293
+
294
+ console.log('\nšŸ“Š Performance Metrics:');
295
+ console.log(` Response Time (Avg): ${summary.performance.responseTime.avg.toFixed(0)}ms`);
296
+ console.log(` Response Time (P95): ${summary.performance.responseTime.p95.toFixed(0)}ms`);
297
+ console.log(` Error Rate: ${(summary.performance.errorRate * 100).toFixed(2)}%`);
298
+ console.log(` Cache Hit Rate: ${(summary.performance.cacheHitRate * 100).toFixed(1)}%`);
299
+
300
+ console.log('\nšŸ’° Cost Metrics:');
301
+ console.log(` Total Tokens: ${summary.cost.totalTokens.toLocaleString()}`);
302
+ console.log(` Estimated Cost: $${summary.cost.estimatedCost.toFixed(2)}`);
303
+ console.log(` Cache Savings: $${summary.cost.savingsFromCache.toFixed(2)}`);
304
+
305
+ console.log('\nāœ… Quality Metrics:');
306
+ console.log(` Validation Success: ${(summary.quality.validationSuccessRate * 100).toFixed(1)}%`);
307
+ console.log(` Test Pass Rate: ${summary.quality.averageTestPassRate.toFixed(1)}%`);
308
+ console.log(` Coverage: ${summary.quality.averageCoverage.toFixed(1)}%`);
309
+
310
+ console.log('\nšŸ”” Alerts:');
311
+ console.log(` Active: ${summary.alerts.active}`);
312
+ console.log(` Total: ${summary.alerts.total}`);
313
+
314
+ console.log('\n' + '='.repeat(80));
315
+ console.log(`Uptime: ${summary.uptime.formatted}`);
316
+ console.log(`Dashboard: http://localhost:${this.dashboard.config.port}`);
317
+ console.log('='.repeat(80) + '\n');
318
+ }
319
+ }
320
+
321
+ // CLI
322
+ if (require.main === module) {
323
+ const monitor = new MigrationMonitor({
324
+ checkInterval: process.env.CHECK_INTERVAL || 60000,
325
+ dashboardPort: process.env.DASHBOARD_PORT || 3000
326
+ });
327
+
328
+ monitor.start().catch(err => {
329
+ console.error('Failed to start monitor:', err);
330
+ process.exit(1);
331
+ });
332
+
333
+ // Generate report every 5 minutes
334
+ setInterval(() => {
335
+ monitor.generateReport();
336
+ }, 300000);
337
+ }
338
+
339
+ module.exports = MigrationMonitor;