diff --git a/simulation-client/src/config/index.js b/simulation-client/src/config/index.js index 80fb317..bf473fd 100644 --- a/simulation-client/src/config/index.js +++ b/simulation-client/src/config/index.js @@ -64,6 +64,15 @@ const config = { errorInjection: { enabled: (process.env.ERROR_INJECTION_ENABLED || 'true') === 'true', probability: parseFloat(process.env.ERROR_INJECTION_PROBABILITY) || 0.05 + }, + + // Scheduled error spikes: crank error probability at fixed minutes each hour + // so every 30-min demo window has a visible spike to investigate. + errorSpike: { + enabled: (process.env.ERROR_SPIKE_ENABLED || 'true') === 'true', + probability: parseFloat(process.env.ERROR_SPIKE_PROBABILITY) || 0.6, + minuteMarks: (process.env.ERROR_SPIKE_MINUTES || '10,40').split(',').map(Number), + durationMinutes: parseInt(process.env.ERROR_SPIKE_DURATION) || 2 } }, diff --git a/simulation-client/src/workflows/SimulationManager.js b/simulation-client/src/workflows/SimulationManager.js index 43b972e..2f17c85 100644 --- a/simulation-client/src/workflows/SimulationManager.js +++ b/simulation-client/src/workflows/SimulationManager.js @@ -295,6 +295,7 @@ class SimulationManager { runtimeMs: runtime, activeSessions: this.activeSessions.size, burstActive: this.burstActive, + errorSpikeActive: this.isErrorSpikeActive(), currentConcurrency: this.getCurrentConcurrency(), totalSessions: this.metrics.totalSessions, successfulSessions: this.metrics.successfulSessions, @@ -311,6 +312,13 @@ class SimulationManager { }; } + isErrorSpikeActive() { + const spike = config.simulation.errorSpike; + if (!spike.enabled) return false; + const minute = new Date().getMinutes(); + return spike.minuteMarks.some(m => minute >= m && minute < m + spike.durationMinutes); + } + delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } diff --git a/simulation-client/src/workflows/UserWorkflow.js b/simulation-client/src/workflows/UserWorkflow.js index d08aeaa..daf41a1 100644 --- a/simulation-client/src/workflows/UserWorkflow.js +++ b/simulation-client/src/workflows/UserWorkflow.js @@ -512,7 +512,16 @@ class UserWorkflow { // (The gateway FaultInjectionFilter adds independent 500/503 noise.) async generateErrorTraffic(user) { if (!config.simulation.errorInjection.enabled) return; - if (Math.random() >= config.simulation.errorInjection.probability) return; + + let effectiveProbability = config.simulation.errorInjection.probability; + const spike = config.simulation.errorSpike; + if (spike.enabled) { + const minute = new Date().getMinutes(); + if (spike.minuteMarks.some(m => minute >= m && minute < m + spike.durationMinutes)) { + effectiveProbability = spike.probability; + } + } + if (Math.random() >= effectiveProbability) return; const account = user.accounts && user.accounts.length > 0 ? user.accounts[0] : null;