blaze-performance-tester 3.0.27 → 3.0.30
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 +16 -107
- package/dist/index.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -74,64 +74,47 @@ try {
|
|
|
74
74
|
process.exit(1);
|
|
75
75
|
}
|
|
76
76
|
var mathUtils = {
|
|
77
|
-
//[cite: 2]
|
|
78
77
|
mean: (arr) => arr.length === 0 ? 0 : arr.reduce((p, c) => p + c, 0) / arr.length,
|
|
79
|
-
//[cite: 2]
|
|
80
78
|
stdDev: (arr, mean) => {
|
|
81
79
|
if (arr.length === 0) return 0;
|
|
82
80
|
const r = arr.reduce((p, c) => p + Math.pow(c - mean, 2), 0);
|
|
83
81
|
return Math.sqrt(r / arr.length);
|
|
84
82
|
},
|
|
85
|
-
//[cite: 2]
|
|
86
83
|
percentile: (arr, p) => {
|
|
87
84
|
if (arr.length === 0) return 0;
|
|
88
85
|
const sorted = [...arr].sort((a, b) => a - b);
|
|
89
86
|
const index = Math.ceil(p / 100 * sorted.length) - 1;
|
|
90
87
|
return sorted[Math.max(0, index)];
|
|
91
88
|
}
|
|
92
|
-
//[cite: 2]
|
|
93
89
|
};
|
|
94
|
-
async function executeTestPipeline() {
|
|
90
|
+
async function executeTestPipeline(config) {
|
|
95
91
|
if (!blazeCore || typeof blazeCore.runCorrelatedTransaction !== "function") {
|
|
96
92
|
console.error("\u274C Error: runCorrelatedTransaction function is missing from the compiled binary bindings.");
|
|
97
93
|
return;
|
|
98
94
|
}
|
|
99
95
|
const transactionalScenario = [
|
|
100
|
-
//[cite: 1]
|
|
101
96
|
{
|
|
102
|
-
//[cite: 1]
|
|
103
97
|
name: "Fetch Target Anti-Forgery Nonce",
|
|
104
|
-
//[cite: 1]
|
|
105
98
|
url: "https://httpbin.org/json",
|
|
106
|
-
// Returns metadata configurations //[cite: 1]
|
|
107
99
|
method: "GET",
|
|
108
|
-
//[cite: 1]
|
|
109
100
|
body: null
|
|
110
|
-
//[cite: 1]
|
|
111
101
|
},
|
|
112
|
-
//[cite: 1]
|
|
113
102
|
{
|
|
114
|
-
//[cite: 1]
|
|
115
103
|
name: "Perform Contextual Post Action",
|
|
116
|
-
//[cite: 1]
|
|
117
|
-
// The engine automatically detects ${csrf_token} if returned in Step 1 and swaps it seamlessly //[cite: 1]
|
|
118
104
|
url: "https://httpbin.org/post?verification=${csrf_token}",
|
|
119
|
-
//[cite: 1]
|
|
120
105
|
method: "POST",
|
|
121
|
-
//[cite: 1]
|
|
122
106
|
body: JSON.stringify({
|
|
123
|
-
//[cite: 1]
|
|
124
107
|
data: "performance_payload",
|
|
125
|
-
//[cite: 1]
|
|
126
108
|
security_token: "${csrf_token}"
|
|
127
|
-
//[cite: 1]
|
|
128
109
|
})
|
|
129
|
-
//[cite: 1]
|
|
130
110
|
}
|
|
131
|
-
//[cite: 1]
|
|
132
111
|
];
|
|
133
|
-
console.log(
|
|
134
|
-
const
|
|
112
|
+
console.log(`Launching automated script transaction analysis for: ${config.targetScript}`);
|
|
113
|
+
const sanitizedSteps = transactionalScenario.map((step) => ({
|
|
114
|
+
...step,
|
|
115
|
+
body: typeof step.body === "string" ? step.body : step.body ? JSON.stringify(step.body) : ""
|
|
116
|
+
}));
|
|
117
|
+
const success = await blazeCore.runCorrelatedTransaction(sanitizedSteps);
|
|
135
118
|
if (success) {
|
|
136
119
|
console.log("Pipeline run complete. Parameter tracking successfully mitigated breaking changes.");
|
|
137
120
|
}
|
|
@@ -144,8 +127,9 @@ async function main() {
|
|
|
144
127
|
}
|
|
145
128
|
const config = parseArguments(args);
|
|
146
129
|
if (config.isCorrelate) {
|
|
147
|
-
await executeTestPipeline();
|
|
148
|
-
}
|
|
130
|
+
await executeTestPipeline(config);
|
|
131
|
+
}
|
|
132
|
+
if (config.isAgentic) {
|
|
149
133
|
await runIntelligentAgenticStressTest(config);
|
|
150
134
|
} else {
|
|
151
135
|
await runStandardStressTest(config);
|
|
@@ -175,6 +159,10 @@ function parseArguments(args) {
|
|
|
175
159
|
if (maxThreadsIdx !== -1) maxThreads = parseInt(args[maxThreadsIdx + 1], 10);
|
|
176
160
|
const outputIdx = args.indexOf("--output");
|
|
177
161
|
if (outputIdx !== -1) outputHtml = args[outputIdx + 1];
|
|
162
|
+
const positionalNums = args.slice(1).filter((arg) => !arg.startsWith("-")).map(Number).filter((n) => !isNaN(n));
|
|
163
|
+
if (positionalNums.length > 0 && threadsIdx === -1 && !isAgentic) threads = positionalNums[0];
|
|
164
|
+
if (positionalNums.length > 1 && durationIdx === -1 && !isAgentic) durationSec = positionalNums[1];
|
|
165
|
+
if (positionalNums.length > 2 && errorIdx === -1 && !isAgentic) targetErrorRate = positionalNums[2] / 100;
|
|
178
166
|
if (isAgentic) {
|
|
179
167
|
const agenticIdx = args.indexOf("--agentic");
|
|
180
168
|
const trailingArgs = args.slice(agenticIdx + 1).filter((arg) => !arg.startsWith("--"));
|
|
@@ -190,31 +178,18 @@ function parseArguments(args) {
|
|
|
190
178
|
if (trailingArgs[2]) targetErrorRate = parseFloat(trailingArgs[2]) / 100;
|
|
191
179
|
}
|
|
192
180
|
return {
|
|
193
|
-
//[cite: 2]
|
|
194
181
|
targetScript,
|
|
195
|
-
//[cite: 2]
|
|
196
182
|
isAgentic,
|
|
197
|
-
//[cite: 2]
|
|
198
183
|
isCorrelate,
|
|
199
|
-
//[cite: 2]
|
|
200
184
|
clusterLogs,
|
|
201
|
-
//[cite: 2]
|
|
202
185
|
threads,
|
|
203
|
-
//[cite: 2]
|
|
204
186
|
durationSec,
|
|
205
|
-
//[cite: 2]
|
|
206
187
|
targetApdex,
|
|
207
|
-
//[cite: 2]
|
|
208
188
|
targetErrorRate,
|
|
209
|
-
//[cite: 2]
|
|
210
189
|
maxThreads,
|
|
211
|
-
//[cite: 2]
|
|
212
190
|
stepSize: 15,
|
|
213
|
-
//[cite: 2]
|
|
214
191
|
maxAllowedLatencyMs,
|
|
215
|
-
//[cite: 2]
|
|
216
192
|
outputHtml
|
|
217
|
-
//[cite: 2]
|
|
218
193
|
};
|
|
219
194
|
}
|
|
220
195
|
async function runBlazeCoreEngine(config) {
|
|
@@ -263,23 +238,14 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
263
238
|
globalMetricsAccumulator.latencies.push(metrics.avgLatencyMs);
|
|
264
239
|
globalMetricsAccumulator.bandwidths.push(metrics.bandwidthMb);
|
|
265
240
|
const currentState = {
|
|
266
|
-
//[cite: 2]
|
|
267
241
|
threads: currentThreads,
|
|
268
|
-
//[cite: 2]
|
|
269
242
|
avgLatency: metrics.avgLatencyMs,
|
|
270
|
-
//[cite: 2]
|
|
271
243
|
p95Latency: metrics.p95LatencyMs,
|
|
272
|
-
//[cite: 2]
|
|
273
244
|
errorRate: metrics.errorRate,
|
|
274
|
-
//[cite: 2]
|
|
275
245
|
apdex: metrics.apdexScore,
|
|
276
|
-
//[cite: 2]
|
|
277
246
|
throughput: metrics.requestsPerSecond,
|
|
278
|
-
//[cite: 2]
|
|
279
247
|
successRequests: metrics.c2xx + metrics.c3xx,
|
|
280
|
-
//[cite: 2]
|
|
281
248
|
failedRequests: metrics.c4xx + metrics.c5xx
|
|
282
|
-
//[cite: 2]
|
|
283
249
|
};
|
|
284
250
|
printMatrixDashboard(metrics, currentThreads);
|
|
285
251
|
history.push(currentState);
|
|
@@ -318,23 +284,14 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
318
284
|
semanticReport = analyzer.process(aggregateErrorLogs);
|
|
319
285
|
}
|
|
320
286
|
const finalSummaryCards = {
|
|
321
|
-
//[cite: 2]
|
|
322
287
|
apdex: history[history.length - 1]?.apdex || 0,
|
|
323
|
-
//[cite: 2]
|
|
324
288
|
throughput: history[history.length - 1]?.throughput || 0,
|
|
325
|
-
//[cite: 2]
|
|
326
289
|
bandwidth: mathUtils.mean(globalMetricsAccumulator.bandwidths),
|
|
327
|
-
//[cite: 2]
|
|
328
290
|
ttfb: mathUtils.mean(globalMetricsAccumulator.ttfb),
|
|
329
|
-
//[cite: 2]
|
|
330
291
|
dns: mathUtils.mean(globalMetricsAccumulator.dns),
|
|
331
|
-
//[cite: 2]
|
|
332
292
|
tcp: mathUtils.mean(globalMetricsAccumulator.tcp),
|
|
333
|
-
//[cite: 2]
|
|
334
293
|
tls: mathUtils.mean(globalMetricsAccumulator.tls),
|
|
335
|
-
//[cite: 2]
|
|
336
294
|
stdDev: mathUtils.stdDev(globalMetricsAccumulator.latencies, mathUtils.mean(globalMetricsAccumulator.latencies))
|
|
337
|
-
//[cite: 2]
|
|
338
295
|
};
|
|
339
296
|
generateFinalAgentReport(history);
|
|
340
297
|
exportHtmlDashboard(history, config, verdictReason, semanticReport, { total2xx, total3xx, total4xx, total5xx }, finalSummaryCards);
|
|
@@ -344,23 +301,14 @@ async function runStandardStressTest(config) {
|
|
|
344
301
|
const { metrics, rawErrors } = await runBlazeCoreEngine(config);
|
|
345
302
|
printMatrixDashboard(metrics, config.threads);
|
|
346
303
|
const history = [{
|
|
347
|
-
//[cite: 2]
|
|
348
304
|
threads: config.threads,
|
|
349
|
-
//[cite: 2]
|
|
350
305
|
avgLatency: metrics.avgLatencyMs,
|
|
351
|
-
//[cite: 2]
|
|
352
306
|
p95Latency: metrics.p95LatencyMs,
|
|
353
|
-
//[cite: 2]
|
|
354
307
|
errorRate: metrics.errorRate,
|
|
355
|
-
//[cite: 2]
|
|
356
308
|
apdex: metrics.apdexScore,
|
|
357
|
-
//[cite: 2]
|
|
358
309
|
throughput: metrics.requestsPerSecond,
|
|
359
|
-
//[cite: 2]
|
|
360
310
|
successRequests: metrics.c2xx + metrics.c3xx,
|
|
361
|
-
//[cite: 2]
|
|
362
311
|
failedRequests: metrics.c4xx + metrics.c5xx
|
|
363
|
-
//[cite: 2]
|
|
364
312
|
}];
|
|
365
313
|
let semanticReport = null;
|
|
366
314
|
if (config.clusterLogs && rawErrors.length > 0) {
|
|
@@ -368,33 +316,22 @@ async function runStandardStressTest(config) {
|
|
|
368
316
|
semanticReport = analyzer.process(rawErrors);
|
|
369
317
|
}
|
|
370
318
|
const finalSummaryCards = {
|
|
371
|
-
//[cite: 2]
|
|
372
319
|
apdex: metrics.apdexScore,
|
|
373
|
-
//[cite: 2]
|
|
374
320
|
throughput: metrics.requestsPerSecond,
|
|
375
|
-
//[cite: 2]
|
|
376
321
|
bandwidth: metrics.bandwidthMb,
|
|
377
|
-
//[cite: 2]
|
|
378
322
|
ttfb: metrics.avgTtfbMs,
|
|
379
|
-
//[cite: 2]
|
|
380
323
|
dns: metrics.avgDnsMs,
|
|
381
|
-
//[cite: 2]
|
|
382
324
|
tcp: metrics.avgTcpMs,
|
|
383
|
-
//[cite: 2]
|
|
384
325
|
tls: metrics.avgTlsMs,
|
|
385
|
-
//[cite: 2]
|
|
386
326
|
stdDev: metrics.stdDevMs
|
|
387
|
-
//[cite: 2]
|
|
388
327
|
};
|
|
389
328
|
const isPassed = metrics.apdexScore >= config.targetApdex && metrics.errorRate <= config.targetErrorRate;
|
|
390
329
|
const verdictReason = isPassed ? "Static single-wave baseline checks concluded successfully without triggering health boundaries." : "Static verification loop completed with values exceeding defined quality thresholds.";
|
|
391
330
|
exportHtmlDashboard(history, config, verdictReason, semanticReport, {
|
|
392
|
-
//[cite: 2]
|
|
393
331
|
total2xx: metrics.c2xx,
|
|
394
332
|
total3xx: metrics.c3xx,
|
|
395
333
|
total4xx: metrics.c4xx,
|
|
396
334
|
total5xx: metrics.c5xx
|
|
397
|
-
//[cite: 2]
|
|
398
335
|
}, finalSummaryCards);
|
|
399
336
|
}
|
|
400
337
|
function generateSimulationData(threads, durationSec, maxAllowedLatencyMs) {
|
|
@@ -405,13 +342,9 @@ function generateSimulationData(threads, durationSec, maxAllowedLatencyMs) {
|
|
|
405
342
|
const isBreached = threads > targetThresholdBreak;
|
|
406
343
|
const stressFactor = isBreached ? Math.pow(threads / targetThresholdBreak, 1.5) : 1;
|
|
407
344
|
const errorPool = [
|
|
408
|
-
//[cite: 2]
|
|
409
345
|
`Error: ECONNREFUSED 127.0.0.1:5432 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1605:16)`,
|
|
410
|
-
//[cite: 2]
|
|
411
346
|
`HTTP/1.1 504 Gateway Timeout on POST /api/v1/checkout - upstream socket drop after 15000ms`,
|
|
412
|
-
//[cite: 2]
|
|
413
347
|
`TypeError: Cannot read properties of undefined (reading 'config_id') at Object.execute (${path.sep}app${path.sep}dist${path.sep}handler.js:42:19)`
|
|
414
|
-
//[cite: 2]
|
|
415
348
|
];
|
|
416
349
|
for (let i = 0; i < totalRequests; i++) {
|
|
417
350
|
const isError = Math.random() < (isBreached ? 0.05 : 1e-3);
|
|
@@ -423,21 +356,13 @@ function generateSimulationData(threads, durationSec, maxAllowedLatencyMs) {
|
|
|
423
356
|
errorMessage = `[${(/* @__PURE__ */ new Date()).toISOString()}] ` + errorPool[Math.floor(Math.random() * errorPool.length)];
|
|
424
357
|
}
|
|
425
358
|
data.push({
|
|
426
|
-
//[cite: 2]
|
|
427
359
|
durationMs: isError ? baseLatency * 0.1 : baseLatency,
|
|
428
|
-
//[cite: 2]
|
|
429
360
|
timestampMs: startTime + Math.random() * (durationSec * 1e3),
|
|
430
|
-
//[cite: 2]
|
|
431
361
|
dnsTimeMs: 1 + Math.random() * 0.9,
|
|
432
|
-
//[cite: 2]
|
|
433
362
|
tcpTimeMs: 4 + Math.random() * 1.5,
|
|
434
|
-
//[cite: 2]
|
|
435
363
|
tlsTimeMs: 6 + Math.random() * 1.8,
|
|
436
|
-
//[cite: 2]
|
|
437
364
|
statusCode,
|
|
438
|
-
//[cite: 2]
|
|
439
365
|
errorMessage
|
|
440
|
-
//[cite: 2]
|
|
441
366
|
});
|
|
442
367
|
}
|
|
443
368
|
return data.sort((a, b) => a.timestampMs - b.timestampMs);
|
|
@@ -467,32 +392,22 @@ function processMetricsTelemetry(requests, durationSec) {
|
|
|
467
392
|
const apdexScore = totalRequests === 0 ? 0 : (satisfied + tolerating / 2) / totalRequests;
|
|
468
393
|
const bandwidthMb = totalRequests * 1.2 / durationSec / 10;
|
|
469
394
|
return {
|
|
470
|
-
//[cite: 2]
|
|
471
395
|
totalRequests,
|
|
472
|
-
//[cite: 2]
|
|
473
396
|
requestsPerSecond: totalRequests / durationSec,
|
|
474
|
-
//[cite: 2]
|
|
475
397
|
avgLatencyMs,
|
|
476
|
-
//[cite: 2]
|
|
477
398
|
stdDevMs,
|
|
478
|
-
//[cite: 2]
|
|
479
399
|
p95LatencyMs,
|
|
480
|
-
//[cite: 2]
|
|
481
400
|
errorRate,
|
|
482
|
-
//[cite: 2]
|
|
483
401
|
apdexScore,
|
|
484
|
-
//[cite: 2]
|
|
485
402
|
c2xx,
|
|
486
403
|
c3xx,
|
|
487
404
|
c4xx,
|
|
488
405
|
c5xx,
|
|
489
|
-
//[cite: 2]
|
|
490
406
|
avgDnsMs,
|
|
491
407
|
avgTcpMs,
|
|
492
408
|
avgTlsMs,
|
|
493
409
|
avgTtfbMs,
|
|
494
410
|
bandwidthMb
|
|
495
|
-
//[cite: 2]
|
|
496
411
|
};
|
|
497
412
|
}
|
|
498
413
|
function printMatrixDashboard(m, threads) {
|
|
@@ -607,8 +522,8 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
607
522
|
|
|
608
523
|
.matrix-box { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.25rem; }
|
|
609
524
|
.matrix-title { font-size: 1.1rem; font-weight: bold; color: #ffffff; margin-bottom: 1rem; }
|
|
610
|
-
.matrix-row { display: flex; justify-content: space-between; align-items: center; padding: 0.6rem 0; border-bottom: 1px solid #1e293b; }
|
|
611
|
-
.matrix-row:last-child { border-bottom: none; }
|
|
525
|
+
.matrix-box .matrix-row { display: flex; justify-content: space-between; align-items: center; padding: 0.6rem 0; border-bottom: 1px solid #1e293b; }
|
|
526
|
+
.matrix-box .matrix-row:last-child { border-bottom: none; }
|
|
612
527
|
.matrix-label { font-size: 0.9rem; color: #f8fafc; display: flex; align-items: center; gap: 0.5rem; }
|
|
613
528
|
.matrix-badge { font-size: 0.7rem; font-weight: bold; padding: 0.1rem 0.3rem; border-radius: 4px; }
|
|
614
529
|
.badge-2xx { background: rgba(22, 163, 74, 0.2); color: #4ade80; }
|
|
@@ -617,7 +532,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
617
532
|
.badge-5xx { background: rgba(220, 38, 38, 0.2); color: #f87171; }
|
|
618
533
|
.matrix-value { font-size: 1rem; font-weight: bold; color: #ffffff; }
|
|
619
534
|
|
|
620
|
-
/* \u{1F4CA} TWO-COLUMN CHART GRID */
|
|
621
535
|
.charts-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin-bottom: 2rem; }
|
|
622
536
|
.graph-card { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.5rem; }
|
|
623
537
|
.graph-title { font-size: 1.1rem; font-weight: 700; color: #ffffff; margin-bottom: 1.2rem; display: flex; align-items: center; gap: 0.5rem; }
|
|
@@ -700,9 +614,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
700
614
|
</div>
|
|
701
615
|
</div>
|
|
702
616
|
|
|
703
|
-
<!-- \u{1F4C9} SPLIT CHARTS SYSTEM -->
|
|
704
617
|
<div class="charts-grid">
|
|
705
|
-
<!-- Chart 1: Volume Streams -->
|
|
706
618
|
<div class="graph-card">
|
|
707
619
|
<div class="graph-title">\u{1F4CA} Throughput Velocity & Workload Volume</div>
|
|
708
620
|
<div style="height: 280px; position: relative;">
|
|
@@ -710,7 +622,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
710
622
|
</div>
|
|
711
623
|
</div>
|
|
712
624
|
|
|
713
|
-
<!-- Chart 2: Concurrency & Health Trends -->
|
|
714
625
|
<div class="graph-card">
|
|
715
626
|
<div class="graph-title">\u{1F504} Active Concurrency (VUs) vs. Time-to-Failure (TTF) Trend</div>
|
|
716
627
|
<div style="height: 280px; position: relative;">
|
|
@@ -753,7 +664,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
753
664
|
<script>
|
|
754
665
|
const labels = ${JSON.stringify(labels)};
|
|
755
666
|
|
|
756
|
-
// \u{1F6E0}\uFE0F Chart 1 Setup: Throughput Bar Streams
|
|
757
667
|
new Chart(document.getElementById('volumeChart'), {
|
|
758
668
|
type: 'bar',
|
|
759
669
|
data: {
|
|
@@ -790,7 +700,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
790
700
|
}
|
|
791
701
|
});
|
|
792
702
|
|
|
793
|
-
// \u{1F6E0}\uFE0F Chart 2 Setup: Concurrency & TTF Correlated Slopes
|
|
794
703
|
new Chart(document.getElementById('concurrencyChart'), {
|
|
795
704
|
type: 'line',
|
|
796
705
|
data: {
|
|
Binary file
|