UNPKG

devflow-ai

Version:

Enterprise-grade AI agent orchestration with swarm management UI dashboard

576 lines (478 loc) 17.9 kB
#!/usr/bin/env node /** * Swarm Load Testing for Claude Flow v2.0.0 */ import { spawn } from 'child_process'; import chalk from 'chalk'; import { SystemIntegration } from '../dist/integration/system-integration.js'; import { SwarmCoordinator } from '../dist/coordination/swarm-coordinator.js'; import { AgentManager } from '../dist/agents/agent-manager.js'; import { TaskEngine } from '../dist/task/engine.js'; // Load test configuration const LOAD_CONFIGS = { light: { swarms: 5, agentsPerSwarm: 8, tasksPerSwarm: 10, duration: 300000, // 5 minutes description: 'Light load test' }, medium: { swarms: 15, agentsPerSwarm: 12, tasksPerSwarm: 20, duration: 600000, // 10 minutes description: 'Medium load test' }, heavy: { swarms: 30, agentsPerSwarm: 20, tasksPerSwarm: 40, duration: 1200000, // 20 minutes description: 'Heavy load test' }, extreme: { swarms: 50, agentsPerSwarm: 30, tasksPerSwarm: 60, duration: 1800000, // 30 minutes description: 'Extreme load test' } }; class SwarmLoadTester { constructor(config) { this.config = config; this.systemIntegration = null; this.swarmCoordinator = null; this.agentManager = null; this.taskEngine = null; this.metrics = { startTime: 0, endTime: 0, swarmsCreated: 0, agentsSpawned: 0, tasksCreated: 0, errors: [], responseTimes: [], throughput: 0 }; this.activeSwarms = new Set(); this.isRunning = false; } log(message, level = 'info') { const timestamp = new Date().toISOString(); const prefix = `[${timestamp}]`; switch (level) { case 'success': console.log(chalk.green(`${prefix}${message}`)); break; case 'error': console.log(chalk.red(`${prefix}${message}`)); break; case 'warning': console.log(chalk.yellow(`${prefix} ⚠️ ${message}`)); break; case 'info': default: console.log(chalk.blue(`${prefix} ℹ️ ${message}`)); break; } } async initialize() { this.log('Initializing system for load testing'); try { this.systemIntegration = SystemIntegration.getInstance(); await this.systemIntegration.initialize({ logLevel: 'warn', // Reduce logging for performance environment: 'testing', monitoring: { enabled: false, // Disable monitoring during load test metrics: false, realTime: false } }); this.swarmCoordinator = this.systemIntegration.getComponent('swarmCoordinator'); this.agentManager = this.systemIntegration.getComponent('agentManager'); this.taskEngine = this.systemIntegration.getComponent('taskEngine'); this.log('System initialized successfully', 'success'); } catch (error) { this.log(`Failed to initialize system: ${error.message}`, 'error'); throw error; } } async runLoadTest() { this.log(`Starting ${this.config.description}`); this.log(`Configuration: ${this.config.swarms} swarms, ${this.config.agentsPerSwarm} agents/swarm, ${this.config.tasksPerSwarm} tasks/swarm`); this.metrics.startTime = Date.now(); this.isRunning = true; try { // Phase 1: Create swarms await this.createSwarms(); // Phase 2: Spawn agents await this.spawnAgents(); // Phase 3: Create tasks await this.createTasks(); // Phase 4: Run for duration await this.runForDuration(); // Phase 5: Cleanup await this.cleanup(); this.metrics.endTime = Date.now(); this.generateReport(); } catch (error) { this.log(`Load test failed: ${error.message}`, 'error'); this.metrics.errors.push({ message: error.message, timestamp: Date.now(), phase: 'main' }); throw error; } finally { this.isRunning = false; } } async createSwarms() { this.log(`Phase 1: Creating ${this.config.swarms} swarms`); const startTime = Date.now(); try { const swarmPromises = Array.from({ length: this.config.swarms }, (_, i) => this.createSwarm(i) ); const swarmIds = await Promise.all(swarmPromises); swarmIds.forEach(id => this.activeSwarms.add(id)); this.metrics.swarmsCreated = swarmIds.length; const duration = Date.now() - startTime; this.log(`Created ${swarmIds.length} swarms in ${duration}ms`, 'success'); } catch (error) { this.log(`Failed to create swarms: ${error.message}`, 'error'); throw error; } } async createSwarm(index) { const swarmStartTime = Date.now(); try { const swarmId = await this.swarmCoordinator.createSwarm({ objective: `Load test swarm ${index}`, strategy: 'auto', topology: 'mesh', maxAgents: this.config.agentsPerSwarm }); const duration = Date.now() - swarmStartTime; this.metrics.responseTimes.push(duration); return swarmId; } catch (error) { this.metrics.errors.push({ message: error.message, timestamp: Date.now(), phase: 'swarm_creation', index }); throw error; } } async spawnAgents() { this.log(`Phase 2: Spawning ${this.config.agentsPerSwarm} agents per swarm`); const startTime = Date.now(); const swarmIds = Array.from(this.activeSwarms); try { const agentPromises = swarmIds.flatMap(swarmId => Array.from({ length: this.config.agentsPerSwarm }, (_, i) => this.spawnAgent(swarmId, i) ) ); const agents = await Promise.all(agentPromises); this.metrics.agentsSpawned = agents.length; const duration = Date.now() - startTime; this.log(`Spawned ${agents.length} agents in ${duration}ms`, 'success'); } catch (error) { this.log(`Failed to spawn agents: ${error.message}`, 'error'); throw error; } } async spawnAgent(swarmId, index) { const agentTypes = ['researcher', 'coder', 'analyst', 'tester', 'coordinator']; const agentType = agentTypes[index % agentTypes.length]; const agentStartTime = Date.now(); try { const agentId = await this.swarmCoordinator.spawnAgentInSwarm(swarmId, { type: agentType, name: `LoadAgent-${index}`, capabilities: ['general', 'load-testing'] }); const duration = Date.now() - agentStartTime; this.metrics.responseTimes.push(duration); return agentId; } catch (error) { this.metrics.errors.push({ message: error.message, timestamp: Date.now(), phase: 'agent_spawning', swarmId, index }); throw error; } } async createTasks() { this.log(`Phase 3: Creating ${this.config.tasksPerSwarm} tasks per swarm`); const startTime = Date.now(); const swarmIds = Array.from(this.activeSwarms); try { const taskPromises = swarmIds.flatMap(swarmId => Array.from({ length: this.config.tasksPerSwarm }, (_, i) => this.createTask(swarmId, i) ) ); const tasks = await Promise.all(taskPromises); this.metrics.tasksCreated = tasks.length; const duration = Date.now() - startTime; this.log(`Created ${tasks.length} tasks in ${duration}ms`, 'success'); } catch (error) { this.log(`Failed to create tasks: ${error.message}`, 'error'); throw error; } } async createTask(swarmId, index) { const taskStartTime = Date.now(); try { const taskId = await this.taskEngine.createTask({ swarmId, type: 'development', objective: `Load test task ${index}`, priority: index % 3 === 0 ? 'high' : 'medium' }); const duration = Date.now() - taskStartTime; this.metrics.responseTimes.push(duration); return taskId; } catch (error) { this.metrics.errors.push({ message: error.message, timestamp: Date.now(), phase: 'task_creation', swarmId, index }); throw error; } } async runForDuration() { this.log(`Phase 4: Running load test for ${this.config.duration / 1000}s`); const endTime = Date.now() + this.config.duration; const checkInterval = 10000; // Check every 10 seconds while (Date.now() < endTime && this.isRunning) { try { // Perform periodic operations to maintain load await this.performPeriodicOperations(); // Report progress const elapsed = Date.now() - this.metrics.startTime; const remaining = endTime - Date.now(); if (elapsed % 60000 < checkInterval) { // Report every minute this.log(`Load test progress: ${Math.floor(elapsed / 1000)}s elapsed, ${Math.floor(remaining / 1000)}s remaining`); await this.reportCurrentMetrics(); } await new Promise(resolve => setTimeout(resolve, checkInterval)); } catch (error) { this.log(`Error during load test execution: ${error.message}`, 'warning'); this.metrics.errors.push({ message: error.message, timestamp: Date.now(), phase: 'execution' }); } } this.log('Load test duration completed', 'success'); } async performPeriodicOperations() { // Perform random operations to maintain load const operations = [ () => this.checkSwarmStatuses(), () => this.checkAgentStatuses(), () => this.checkTaskStatuses(), () => this.performHealthChecks() ]; const randomOperation = operations[Math.floor(Math.random() * operations.length)]; await randomOperation(); } async checkSwarmStatuses() { const swarmIds = Array.from(this.activeSwarms); const randomSwarmId = swarmIds[Math.floor(Math.random() * swarmIds.length)]; if (randomSwarmId) { const startTime = Date.now(); await this.swarmCoordinator.getSwarmStatus(randomSwarmId); const duration = Date.now() - startTime; this.metrics.responseTimes.push(duration); } } async checkAgentStatuses() { const startTime = Date.now(); await this.agentManager.listAgents(); const duration = Date.now() - startTime; this.metrics.responseTimes.push(duration); } async checkTaskStatuses() { const swarmIds = Array.from(this.activeSwarms); const randomSwarmId = swarmIds[Math.floor(Math.random() * swarmIds.length)]; if (randomSwarmId) { const startTime = Date.now(); await this.taskEngine.getActiveTasks(randomSwarmId); const duration = Date.now() - startTime; this.metrics.responseTimes.push(duration); } } async performHealthChecks() { const startTime = Date.now(); await this.systemIntegration.getSystemHealth(); const duration = Date.now() - startTime; this.metrics.responseTimes.push(duration); } async reportCurrentMetrics() { try { const health = await this.systemIntegration.getSystemHealth(); const avgResponseTime = this.metrics.responseTimes.length > 0 ? this.metrics.responseTimes.reduce((sum, time) => sum + time, 0) / this.metrics.responseTimes.length : 0; this.log(`Current metrics: ${health.metrics.healthyComponents}/${health.metrics.totalComponents} components healthy, avg response: ${avgResponseTime.toFixed(2)}ms`); } catch (error) { this.log(`Failed to get current metrics: ${error.message}`, 'warning'); } } async cleanup() { this.log('Phase 5: Cleaning up resources'); try { // Shutdown system gracefully await this.systemIntegration.shutdown(); this.log('Cleanup completed successfully', 'success'); } catch (error) { this.log(`Cleanup failed: ${error.message}`, 'warning'); } } generateReport() { const totalDuration = this.metrics.endTime - this.metrics.startTime; const avgResponseTime = this.metrics.responseTimes.length > 0 ? this.metrics.responseTimes.reduce((sum, time) => sum + time, 0) / this.metrics.responseTimes.length : 0; const maxResponseTime = this.metrics.responseTimes.length > 0 ? Math.max(...this.metrics.responseTimes) : 0; const minResponseTime = this.metrics.responseTimes.length > 0 ? Math.min(...this.metrics.responseTimes) : 0; const totalOperations = this.metrics.swarmsCreated + this.metrics.agentsSpawned + this.metrics.tasksCreated; const throughput = totalOperations / (totalDuration / 1000); console.log('\n' + '='.repeat(80)); console.log(chalk.bold.blue('🔥 SWARM LOAD TEST REPORT')); console.log('='.repeat(80)); console.log(`\n📊 Test Configuration:`); console.log(` Description: ${this.config.description}`); console.log(` Swarms: ${this.config.swarms}`); console.log(` Agents per Swarm: ${this.config.agentsPerSwarm}`); console.log(` Tasks per Swarm: ${this.config.tasksPerSwarm}`); console.log(` Duration: ${this.config.duration / 1000}s`); console.log(`\n⏱️ Execution Metrics:`); console.log(` Total Duration: ${(totalDuration / 1000).toFixed(2)}s`); console.log(` Swarms Created: ${chalk.green(this.metrics.swarmsCreated)}`); console.log(` Agents Spawned: ${chalk.green(this.metrics.agentsSpawned)}`); console.log(` Tasks Created: ${chalk.green(this.metrics.tasksCreated)}`); console.log(` Total Operations: ${chalk.cyan(totalOperations)}`); console.log(` Throughput: ${chalk.yellow(throughput.toFixed(2))} ops/sec`); console.log(`\n🚀 Performance Metrics:`); console.log(` Average Response Time: ${chalk.cyan(avgResponseTime.toFixed(2))}ms`); console.log(` Min Response Time: ${chalk.green(minResponseTime.toFixed(2))}ms`); console.log(` Max Response Time: ${chalk.yellow(maxResponseTime.toFixed(2))}ms`); console.log(` Total Requests: ${chalk.blue(this.metrics.responseTimes.length)}`); if (this.metrics.errors.length > 0) { console.log(`\n❌ Errors (${this.metrics.errors.length}):`); const errorsByPhase = this.metrics.errors.reduce((acc, error) => { acc[error.phase] = (acc[error.phase] || 0) + 1; return acc; }, {}); Object.entries(errorsByPhase).forEach(([phase, count]) => { console.log(` ${phase}: ${chalk.red(count)} errors`); }); const errorRate = (this.metrics.errors.length / totalOperations) * 100; console.log(` Error Rate: ${chalk.red(errorRate.toFixed(2))}%`); } else { console.log(`\n✅ No errors detected!`); } // Performance assessment console.log(`\n📈 Performance Assessment:`); if (avgResponseTime < 100) { console.log(` Response Time: ${chalk.green('EXCELLENT')} (< 100ms)`); } else if (avgResponseTime < 500) { console.log(` Response Time: ${chalk.yellow('GOOD')} (100-500ms)`); } else if (avgResponseTime < 1000) { console.log(` Response Time: ${chalk.yellow('ACCEPTABLE')} (500-1000ms)`); } else { console.log(` Response Time: ${chalk.red('POOR')} (> 1000ms)`); } if (throughput > 50) { console.log(` Throughput: ${chalk.green('EXCELLENT')} (> 50 ops/sec)`); } else if (throughput > 20) { console.log(` Throughput: ${chalk.yellow('GOOD')} (20-50 ops/sec)`); } else if (throughput > 10) { console.log(` Throughput: ${chalk.yellow('ACCEPTABLE')} (10-20 ops/sec)`); } else { console.log(` Throughput: ${chalk.red('POOR')} (< 10 ops/sec)`); } const errorRate = (this.metrics.errors.length / totalOperations) * 100; if (errorRate === 0) { console.log(` Reliability: ${chalk.green('EXCELLENT')} (0% errors)`); } else if (errorRate < 1) { console.log(` Reliability: ${chalk.yellow('GOOD')} (< 1% errors)`); } else if (errorRate < 5) { console.log(` Reliability: ${chalk.yellow('ACCEPTABLE')} (1-5% errors)`); } else { console.log(` Reliability: ${chalk.red('POOR')} (> 5% errors)`); } console.log('\n' + '='.repeat(80)); // Save detailed report to file const reportData = { config: this.config, metrics: this.metrics, summary: { totalDuration, avgResponseTime, maxResponseTime, minResponseTime, totalOperations, throughput, errorRate }, timestamp: new Date().toISOString() }; return reportData; } } async function main() { const args = process.argv.slice(2); const configName = args[0] || 'light'; if (!LOAD_CONFIGS[configName]) { console.error(chalk.red(`Unknown load config: ${configName}`)); console.log(chalk.blue('Available configs:')); Object.entries(LOAD_CONFIGS).forEach(([name, config]) => { console.log(` ${name}: ${config.description}`); }); process.exit(1); } const config = LOAD_CONFIGS[configName]; const tester = new SwarmLoadTester(config); try { await tester.initialize(); await tester.runLoadTest(); process.exit(0); } catch (error) { console.error(chalk.red('Load test failed:'), error.message); process.exit(1); } } // Handle graceful shutdown process.on('SIGINT', () => { console.log(chalk.yellow('\nReceived SIGINT, shutting down gracefully...')); process.exit(0); }); process.on('SIGTERM', () => { console.log(chalk.yellow('\nReceived SIGTERM, shutting down gracefully...')); process.exit(0); }); if (import.meta.url === `file://${process.argv[1]}`) { main(); }