blaze-performance-tester 3.0.1 → 3.0.4
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/dist/cli.js +84 -10
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -22,6 +22,12 @@ var mathUtils = {
|
|
|
22
22
|
if (arr.length === 0) return 0;
|
|
23
23
|
const r = arr.reduce((p, c) => p + Math.pow(c - mean, 2), 0);
|
|
24
24
|
return Math.sqrt(r / arr.length);
|
|
25
|
+
},
|
|
26
|
+
percentile: (arr, p) => {
|
|
27
|
+
if (arr.length === 0) return 0;
|
|
28
|
+
const sorted = [...arr].sort((a, b) => a - b);
|
|
29
|
+
const index = Math.ceil(p / 100 * sorted.length) - 1;
|
|
30
|
+
return sorted[Math.max(0, index)];
|
|
25
31
|
}
|
|
26
32
|
};
|
|
27
33
|
async function main() {
|
|
@@ -95,6 +101,7 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
95
101
|
let currentThreads = Math.max(5, Math.floor(config.threads * 0.5));
|
|
96
102
|
let baseStep = config.stepSize;
|
|
97
103
|
let isStable = true;
|
|
104
|
+
let verdictReason = "The system successfully scaled and remained stable within parameters up to maximum configured capacity allocations.";
|
|
98
105
|
while (currentThreads <= config.maxThreads && isStable) {
|
|
99
106
|
console.log(`
|
|
100
107
|
\u{1F916} [Agent Decision]: Testing execution tier at ${currentThreads} concurrent threads...`);
|
|
@@ -102,6 +109,7 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
102
109
|
const currentState = {
|
|
103
110
|
threads: currentThreads,
|
|
104
111
|
avgLatency: metrics.avgLatencyMs,
|
|
112
|
+
p95Latency: metrics.p95LatencyMs,
|
|
105
113
|
errorRate: metrics.errorRate,
|
|
106
114
|
apdex: metrics.apdexScore,
|
|
107
115
|
throughput: metrics.requestsPerSecond
|
|
@@ -114,7 +122,8 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
114
122
|
const dLatency_dThreads = (current.avgLatency - previous.avgLatency) / (current.threads - previous.threads);
|
|
115
123
|
console.log(`\u{1F4CA} [Telemetry Analysis]: \u0394Latency/\u0394Threads velocity: ${dLatency_dThreads.toFixed(2)}ms/thread`);
|
|
116
124
|
if (current.throughput <= previous.throughput * 1.02 && dLatency_dThreads > 4.5) {
|
|
117
|
-
|
|
125
|
+
verdictReason = "The primary breakdown point was identified due to infrastructure saturation where throughput flattened while latency spiked rapidly.";
|
|
126
|
+
console.log(`\u26A0\uFE0F [Agent Alert]: ${verdictReason} Backing off.`);
|
|
118
127
|
currentThreads = Math.floor(currentThreads * 0.8);
|
|
119
128
|
isStable = false;
|
|
120
129
|
break;
|
|
@@ -125,8 +134,15 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
125
134
|
baseStep = Math.max(2, Math.floor(baseStep * 0.35));
|
|
126
135
|
}
|
|
127
136
|
}
|
|
128
|
-
if (currentState.apdex < config.targetApdex
|
|
129
|
-
|
|
137
|
+
if (currentState.apdex < config.targetApdex) {
|
|
138
|
+
verdictReason = "The primary breakdown point was identified due to latency metrics breaching target limits and driving Apdex scores below thresholds.";
|
|
139
|
+
console.log(`\u{1F6D1} [SLO Breach]: Critical thresholds violated. Apdex: ${currentState.apdex.toFixed(2)}`);
|
|
140
|
+
isStable = false;
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
if (currentState.errorRate > config.targetErrorRate) {
|
|
144
|
+
verdictReason = "The primary breakdown point was identified due to HTTP error rates spiking past target service level boundaries.";
|
|
145
|
+
console.log(`\u{1F6D1} [SLO Breach]: Critical thresholds violated. Errors: ${(currentState.errorRate * 100).toFixed(2)}%`);
|
|
130
146
|
isStable = false;
|
|
131
147
|
break;
|
|
132
148
|
}
|
|
@@ -137,7 +153,7 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
137
153
|
currentThreads += nextStep;
|
|
138
154
|
}
|
|
139
155
|
generateFinalAgentReport(history);
|
|
140
|
-
exportHtmlDashboard(history, config);
|
|
156
|
+
exportHtmlDashboard(history, config, verdictReason);
|
|
141
157
|
}
|
|
142
158
|
async function runStandardStressTest(config) {
|
|
143
159
|
console.log(`\u{1F3CB}\uFE0F Running Standard Stress Test [Threads: ${config.threads} | Duration: ${config.durationSec}s]`);
|
|
@@ -146,11 +162,14 @@ async function runStandardStressTest(config) {
|
|
|
146
162
|
const history = [{
|
|
147
163
|
threads: config.threads,
|
|
148
164
|
avgLatency: metrics.avgLatencyMs,
|
|
165
|
+
p95Latency: metrics.p95LatencyMs,
|
|
149
166
|
errorRate: metrics.errorRate,
|
|
150
167
|
apdex: metrics.apdexScore,
|
|
151
168
|
throughput: metrics.requestsPerSecond
|
|
152
169
|
}];
|
|
153
|
-
|
|
170
|
+
const isPassed = metrics.apdexScore >= config.targetApdex && metrics.errorRate <= config.targetErrorRate;
|
|
171
|
+
const verdictReason = isPassed ? "Static single-wave baseline checks concluded successfully without triggering health boundaries." : "Static verification loop completed with values exceeding defined quality thresholds.";
|
|
172
|
+
exportHtmlDashboard(history, config, verdictReason);
|
|
154
173
|
}
|
|
155
174
|
function generateSimulationData(threads, durationSec) {
|
|
156
175
|
const data = [];
|
|
@@ -176,6 +195,7 @@ function processMetricsTelemetry(requests, durationSec) {
|
|
|
176
195
|
const durations = requests.map((r) => r.durationMs);
|
|
177
196
|
const avgLatencyMs = mathUtils.mean(durations);
|
|
178
197
|
const stdDevMs = mathUtils.stdDev(durations, avgLatencyMs);
|
|
198
|
+
const p95LatencyMs = mathUtils.percentile(durations, 95);
|
|
179
199
|
const errorCount = requests.filter((r) => r.statusCode >= 400).length;
|
|
180
200
|
const errorRate = errorCount / totalRequests;
|
|
181
201
|
const T = 100;
|
|
@@ -187,6 +207,7 @@ function processMetricsTelemetry(requests, durationSec) {
|
|
|
187
207
|
requestsPerSecond: totalRequests / durationSec,
|
|
188
208
|
avgLatencyMs,
|
|
189
209
|
stdDevMs,
|
|
210
|
+
p95LatencyMs,
|
|
190
211
|
errorRate,
|
|
191
212
|
apdexScore
|
|
192
213
|
};
|
|
@@ -194,10 +215,10 @@ function processMetricsTelemetry(requests, durationSec) {
|
|
|
194
215
|
function printMatrixDashboard(m, threads) {
|
|
195
216
|
const pad = (val, size) => String(val).padEnd(size).substring(0, size);
|
|
196
217
|
console.log(`-----------------------------------------------------------------------------------------`);
|
|
197
|
-
console.log(`| Threads | Samples | Avg Latency |
|
|
218
|
+
console.log(`| Threads | Samples | Avg Latency | P95 Latency | Throughput | Error Rate | Apdex |`);
|
|
198
219
|
console.log(`-----------------------------------------------------------------------------------------`);
|
|
199
220
|
console.log(
|
|
200
|
-
`| ${pad(threads, 7)} | ${pad(m.totalRequests, 9)} | ${pad(m.avgLatencyMs.toFixed(1) + "ms", 11)} | ${pad(m.
|
|
221
|
+
`| ${pad(threads, 7)} | ${pad(m.totalRequests, 9)} | ${pad(m.avgLatencyMs.toFixed(1) + "ms", 11)} | ${pad(m.p95LatencyMs.toFixed(1) + "ms", 11)} | ${pad(m.requestsPerSecond.toFixed(0) + "/s", 10)} | ${pad((m.errorRate * 100).toFixed(2) + "%", 10)} | ${pad(m.apdexScore.toFixed(2), 9)} |`
|
|
201
222
|
);
|
|
202
223
|
console.log(`-----------------------------------------------------------------------------------------`);
|
|
203
224
|
}
|
|
@@ -214,12 +235,14 @@ function generateFinalAgentReport(history) {
|
|
|
214
235
|
console.log(`\u26A1 Peak Achieved Cluster Velocity : ${peakThroughput.toFixed(0)} req/sec`);
|
|
215
236
|
console.log("=======================================================\n");
|
|
216
237
|
}
|
|
217
|
-
function exportHtmlDashboard(history, config) {
|
|
238
|
+
function exportHtmlDashboard(history, config, verdictReason) {
|
|
218
239
|
const labels = history.map((h) => `${h.threads} Threads`);
|
|
219
240
|
const throughputData = history.map((h) => h.throughput.toFixed(0));
|
|
220
241
|
const latencyData = history.map((h) => h.avgLatency.toFixed(1));
|
|
221
242
|
const errorData = history.map((h) => (h.errorRate * 100).toFixed(2));
|
|
222
|
-
const
|
|
243
|
+
const waveListItems = history.map((h) => {
|
|
244
|
+
return `<div class="wave-item">Wave (${h.threads} VUs): P95 ${h.p95Latency.toFixed(1)}ms, Errors ${(h.errorRate * 100).toFixed(1)}%</div>`;
|
|
245
|
+
}).join("");
|
|
223
246
|
const htmlContent = `<!DOCTYPE html>
|
|
224
247
|
<html lang="en">
|
|
225
248
|
<head>
|
|
@@ -229,9 +252,46 @@ function exportHtmlDashboard(history, config) {
|
|
|
229
252
|
<style>
|
|
230
253
|
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0f172a; color: #f8fafc; margin: 0; padding: 2rem; }
|
|
231
254
|
.container { max-width: 1200px; margin: 0 auto; }
|
|
232
|
-
.header { border-bottom: 1px solid #334155; padding-bottom: 1rem; margin-bottom:
|
|
255
|
+
.header { border-bottom: 1px solid #334155; padding-bottom: 1rem; margin-bottom: 1.5rem; }
|
|
233
256
|
h1 { color: #38bdf8; margin: 0; font-size: 2rem; }
|
|
234
257
|
.meta { color: #94a3b8; font-size: 0.9rem; margin-top: 0.5rem; }
|
|
258
|
+
|
|
259
|
+
/* \u{1F916} AI VERDICT COMPONENT STYLING */
|
|
260
|
+
.verdict-box {
|
|
261
|
+
background: #111827;
|
|
262
|
+
border: 1px dashed #ea580c;
|
|
263
|
+
border-radius: 8px;
|
|
264
|
+
padding: 1.25rem;
|
|
265
|
+
margin-bottom: 2rem;
|
|
266
|
+
}
|
|
267
|
+
.verdict-title {
|
|
268
|
+
text-transform: uppercase;
|
|
269
|
+
font-size: 0.85rem;
|
|
270
|
+
font-weight: 700;
|
|
271
|
+
color: #f97316;
|
|
272
|
+
margin-bottom: 0.5rem;
|
|
273
|
+
display: flex;
|
|
274
|
+
align-items: center;
|
|
275
|
+
gap: 0.4rem;
|
|
276
|
+
}
|
|
277
|
+
.verdict-text {
|
|
278
|
+
font-size: 0.95rem;
|
|
279
|
+
line-height: 1.5;
|
|
280
|
+
color: #e2e8f0;
|
|
281
|
+
margin-bottom: 0.75rem;
|
|
282
|
+
}
|
|
283
|
+
.verdict-waves {
|
|
284
|
+
background: #1f2937;
|
|
285
|
+
border-radius: 6px;
|
|
286
|
+
padding: 0.75rem 1rem;
|
|
287
|
+
font-family: monospace;
|
|
288
|
+
color: #9ca3af;
|
|
289
|
+
font-size: 0.9rem;
|
|
290
|
+
}
|
|
291
|
+
.wave-item {
|
|
292
|
+
margin: 0.25rem 0;
|
|
293
|
+
}
|
|
294
|
+
|
|
235
295
|
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(500px, 1fr)); gap: 2rem; margin-bottom: 2rem; }
|
|
236
296
|
.card { background: #1e293b; border: 1px solid #334155; border-radius: 8px; padding: 1.5rem; }
|
|
237
297
|
h3 { margin-top: 0; color: #cbd5e1; border-bottom: 1px solid #334155; padding-bottom: 0.5rem; }
|
|
@@ -251,6 +311,18 @@ function exportHtmlDashboard(history, config) {
|
|
|
251
311
|
<div class="meta">Target Script: <code>${config.targetScript}</code> | Mode: ${config.isAgentic ? "\u{1F9E0} Intelligent Agentic" : "\u{1F3CB}\uFE0F Fixed Workload"}</div>
|
|
252
312
|
</div>
|
|
253
313
|
|
|
314
|
+
<!-- \u{1F916} AUTOMATED VERDICT CONTAINER -->
|
|
315
|
+
<div class="verdict-box">
|
|
316
|
+
<div class="verdict-title">\u{1F916} AI Stress-Testing Agent Verdict</div>
|
|
317
|
+
<div class="verdict-text">
|
|
318
|
+
Blaze Agent auto-evaluated execution telemetry across <strong>${history.length} test waves</strong>.
|
|
319
|
+
${verdictReason}
|
|
320
|
+
</div>
|
|
321
|
+
<div class="verdict-waves">
|
|
322
|
+
${waveListItems}
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
|
|
254
326
|
<div class="grid">
|
|
255
327
|
<div class="card"><canvas id="throughputChart"></canvas></div>
|
|
256
328
|
<div class="card"><canvas id="latencyChart"></canvas></div>
|
|
@@ -264,6 +336,7 @@ function exportHtmlDashboard(history, config) {
|
|
|
264
336
|
<th>Concurrency (Threads)</th>
|
|
265
337
|
<th>Throughput</th>
|
|
266
338
|
<th>Avg Latency</th>
|
|
339
|
+
<th>P95 Latency</th>
|
|
267
340
|
<th>Error Rate</th>
|
|
268
341
|
<th>Apdex Score</th>
|
|
269
342
|
<th>Status</th>
|
|
@@ -277,6 +350,7 @@ function exportHtmlDashboard(history, config) {
|
|
|
277
350
|
<td><strong>${h.threads}</strong></td>
|
|
278
351
|
<td>${h.throughput.toFixed(0)} req/sec</td>
|
|
279
352
|
<td>${h.avgLatency.toFixed(1)} ms</td>
|
|
353
|
+
<td>${h.p95Latency.toFixed(1)} ms</td>
|
|
280
354
|
<td>${(h.errorRate * 100).toFixed(2)}%</td>
|
|
281
355
|
<td>${h.apdex.toFixed(2)}</td>
|
|
282
356
|
<td>
|
|
Binary file
|