blaze-performance-tester 3.0.22 → 3.0.24
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 +186 -33
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -74,19 +74,68 @@ try {
|
|
|
74
74
|
process.exit(1);
|
|
75
75
|
}
|
|
76
76
|
var mathUtils = {
|
|
77
|
+
//[cite: 2]
|
|
77
78
|
mean: (arr) => arr.length === 0 ? 0 : arr.reduce((p, c) => p + c, 0) / arr.length,
|
|
79
|
+
//[cite: 2]
|
|
78
80
|
stdDev: (arr, mean) => {
|
|
79
81
|
if (arr.length === 0) return 0;
|
|
80
82
|
const r = arr.reduce((p, c) => p + Math.pow(c - mean, 2), 0);
|
|
81
83
|
return Math.sqrt(r / arr.length);
|
|
82
84
|
},
|
|
85
|
+
//[cite: 2]
|
|
83
86
|
percentile: (arr, p) => {
|
|
84
87
|
if (arr.length === 0) return 0;
|
|
85
88
|
const sorted = [...arr].sort((a, b) => a - b);
|
|
86
89
|
const index = Math.ceil(p / 100 * sorted.length) - 1;
|
|
87
90
|
return sorted[Math.max(0, index)];
|
|
88
91
|
}
|
|
92
|
+
//[cite: 2]
|
|
89
93
|
};
|
|
94
|
+
async function executeTestPipeline() {
|
|
95
|
+
if (!blazeCore || typeof blazeCore.runCorrelatedTransaction !== "function") {
|
|
96
|
+
console.error("\u274C Error: runCorrelatedTransaction function is missing from the compiled binary bindings.");
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const transactionalScenario = [
|
|
100
|
+
//[cite: 1]
|
|
101
|
+
{
|
|
102
|
+
//[cite: 1]
|
|
103
|
+
name: "Fetch Target Anti-Forgery Nonce",
|
|
104
|
+
//[cite: 1]
|
|
105
|
+
url: "https://httpbin.org/json",
|
|
106
|
+
// Returns metadata configurations //[cite: 1]
|
|
107
|
+
method: "GET",
|
|
108
|
+
//[cite: 1]
|
|
109
|
+
body: null
|
|
110
|
+
//[cite: 1]
|
|
111
|
+
},
|
|
112
|
+
//[cite: 1]
|
|
113
|
+
{
|
|
114
|
+
//[cite: 1]
|
|
115
|
+
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
|
+
url: "https://httpbin.org/post?verification=${csrf_token}",
|
|
119
|
+
//[cite: 1]
|
|
120
|
+
method: "POST",
|
|
121
|
+
//[cite: 1]
|
|
122
|
+
body: JSON.stringify({
|
|
123
|
+
//[cite: 1]
|
|
124
|
+
data: "performance_payload",
|
|
125
|
+
//[cite: 1]
|
|
126
|
+
security_token: "${csrf_token}"
|
|
127
|
+
//[cite: 1]
|
|
128
|
+
})
|
|
129
|
+
//[cite: 1]
|
|
130
|
+
}
|
|
131
|
+
//[cite: 1]
|
|
132
|
+
];
|
|
133
|
+
console.log("Launching automated script transaction analysis...");
|
|
134
|
+
const success = await blazeCore.runCorrelatedTransaction(transactionalScenario);
|
|
135
|
+
if (success) {
|
|
136
|
+
console.log("Pipeline run complete. Parameter tracking successfully mitigated breaking changes.");
|
|
137
|
+
}
|
|
138
|
+
}
|
|
90
139
|
async function main() {
|
|
91
140
|
const args = process.argv.slice(2);
|
|
92
141
|
if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
|
|
@@ -94,7 +143,9 @@ async function main() {
|
|
|
94
143
|
return;
|
|
95
144
|
}
|
|
96
145
|
const config = parseArguments(args);
|
|
97
|
-
if (config.
|
|
146
|
+
if (config.isCorrelate) {
|
|
147
|
+
await executeTestPipeline();
|
|
148
|
+
} else if (config.isAgentic) {
|
|
98
149
|
await runIntelligentAgenticStressTest(config);
|
|
99
150
|
} else {
|
|
100
151
|
await runStandardStressTest(config);
|
|
@@ -103,6 +154,7 @@ async function main() {
|
|
|
103
154
|
function parseArguments(args) {
|
|
104
155
|
const targetScript = path.resolve(args[0] || ".");
|
|
105
156
|
const isAgentic = args.includes("--agentic");
|
|
157
|
+
const isCorrelate = args.includes("--correlate");
|
|
106
158
|
const clusterLogs = args.includes("--cluster-logs");
|
|
107
159
|
let threads = 10;
|
|
108
160
|
let durationSec = 10;
|
|
@@ -138,17 +190,31 @@ function parseArguments(args) {
|
|
|
138
190
|
if (trailingArgs[2]) targetErrorRate = parseFloat(trailingArgs[2]) / 100;
|
|
139
191
|
}
|
|
140
192
|
return {
|
|
193
|
+
//[cite: 2]
|
|
141
194
|
targetScript,
|
|
195
|
+
//[cite: 2]
|
|
142
196
|
isAgentic,
|
|
197
|
+
//[cite: 2]
|
|
198
|
+
isCorrelate,
|
|
199
|
+
//[cite: 2]
|
|
143
200
|
clusterLogs,
|
|
201
|
+
//[cite: 2]
|
|
144
202
|
threads,
|
|
203
|
+
//[cite: 2]
|
|
145
204
|
durationSec,
|
|
205
|
+
//[cite: 2]
|
|
146
206
|
targetApdex,
|
|
207
|
+
//[cite: 2]
|
|
147
208
|
targetErrorRate,
|
|
209
|
+
//[cite: 2]
|
|
148
210
|
maxThreads,
|
|
211
|
+
//[cite: 2]
|
|
149
212
|
stepSize: 15,
|
|
213
|
+
//[cite: 2]
|
|
150
214
|
maxAllowedLatencyMs,
|
|
215
|
+
//[cite: 2]
|
|
151
216
|
outputHtml
|
|
217
|
+
//[cite: 2]
|
|
152
218
|
};
|
|
153
219
|
}
|
|
154
220
|
async function runBlazeCoreEngine(config) {
|
|
@@ -197,14 +263,23 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
197
263
|
globalMetricsAccumulator.latencies.push(metrics.avgLatencyMs);
|
|
198
264
|
globalMetricsAccumulator.bandwidths.push(metrics.bandwidthMb);
|
|
199
265
|
const currentState = {
|
|
266
|
+
//[cite: 2]
|
|
200
267
|
threads: currentThreads,
|
|
268
|
+
//[cite: 2]
|
|
201
269
|
avgLatency: metrics.avgLatencyMs,
|
|
270
|
+
//[cite: 2]
|
|
202
271
|
p95Latency: metrics.p95LatencyMs,
|
|
272
|
+
//[cite: 2]
|
|
203
273
|
errorRate: metrics.errorRate,
|
|
274
|
+
//[cite: 2]
|
|
204
275
|
apdex: metrics.apdexScore,
|
|
276
|
+
//[cite: 2]
|
|
205
277
|
throughput: metrics.requestsPerSecond,
|
|
278
|
+
//[cite: 2]
|
|
206
279
|
successRequests: metrics.c2xx + metrics.c3xx,
|
|
280
|
+
//[cite: 2]
|
|
207
281
|
failedRequests: metrics.c4xx + metrics.c5xx
|
|
282
|
+
//[cite: 2]
|
|
208
283
|
};
|
|
209
284
|
printMatrixDashboard(metrics, currentThreads);
|
|
210
285
|
history.push(currentState);
|
|
@@ -243,14 +318,23 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
243
318
|
semanticReport = analyzer.process(aggregateErrorLogs);
|
|
244
319
|
}
|
|
245
320
|
const finalSummaryCards = {
|
|
321
|
+
//[cite: 2]
|
|
246
322
|
apdex: history[history.length - 1]?.apdex || 0,
|
|
323
|
+
//[cite: 2]
|
|
247
324
|
throughput: history[history.length - 1]?.throughput || 0,
|
|
325
|
+
//[cite: 2]
|
|
248
326
|
bandwidth: mathUtils.mean(globalMetricsAccumulator.bandwidths),
|
|
327
|
+
//[cite: 2]
|
|
249
328
|
ttfb: mathUtils.mean(globalMetricsAccumulator.ttfb),
|
|
329
|
+
//[cite: 2]
|
|
250
330
|
dns: mathUtils.mean(globalMetricsAccumulator.dns),
|
|
331
|
+
//[cite: 2]
|
|
251
332
|
tcp: mathUtils.mean(globalMetricsAccumulator.tcp),
|
|
333
|
+
//[cite: 2]
|
|
252
334
|
tls: mathUtils.mean(globalMetricsAccumulator.tls),
|
|
335
|
+
//[cite: 2]
|
|
253
336
|
stdDev: mathUtils.stdDev(globalMetricsAccumulator.latencies, mathUtils.mean(globalMetricsAccumulator.latencies))
|
|
337
|
+
//[cite: 2]
|
|
254
338
|
};
|
|
255
339
|
generateFinalAgentReport(history);
|
|
256
340
|
exportHtmlDashboard(history, config, verdictReason, semanticReport, { total2xx, total3xx, total4xx, total5xx }, finalSummaryCards);
|
|
@@ -260,14 +344,23 @@ async function runStandardStressTest(config) {
|
|
|
260
344
|
const { metrics, rawErrors } = await runBlazeCoreEngine(config);
|
|
261
345
|
printMatrixDashboard(metrics, config.threads);
|
|
262
346
|
const history = [{
|
|
347
|
+
//[cite: 2]
|
|
263
348
|
threads: config.threads,
|
|
349
|
+
//[cite: 2]
|
|
264
350
|
avgLatency: metrics.avgLatencyMs,
|
|
351
|
+
//[cite: 2]
|
|
265
352
|
p95Latency: metrics.p95LatencyMs,
|
|
353
|
+
//[cite: 2]
|
|
266
354
|
errorRate: metrics.errorRate,
|
|
355
|
+
//[cite: 2]
|
|
267
356
|
apdex: metrics.apdexScore,
|
|
357
|
+
//[cite: 2]
|
|
268
358
|
throughput: metrics.requestsPerSecond,
|
|
359
|
+
//[cite: 2]
|
|
269
360
|
successRequests: metrics.c2xx + metrics.c3xx,
|
|
361
|
+
//[cite: 2]
|
|
270
362
|
failedRequests: metrics.c4xx + metrics.c5xx
|
|
363
|
+
//[cite: 2]
|
|
271
364
|
}];
|
|
272
365
|
let semanticReport = null;
|
|
273
366
|
if (config.clusterLogs && rawErrors.length > 0) {
|
|
@@ -275,22 +368,33 @@ async function runStandardStressTest(config) {
|
|
|
275
368
|
semanticReport = analyzer.process(rawErrors);
|
|
276
369
|
}
|
|
277
370
|
const finalSummaryCards = {
|
|
371
|
+
//[cite: 2]
|
|
278
372
|
apdex: metrics.apdexScore,
|
|
373
|
+
//[cite: 2]
|
|
279
374
|
throughput: metrics.requestsPerSecond,
|
|
375
|
+
//[cite: 2]
|
|
280
376
|
bandwidth: metrics.bandwidthMb,
|
|
377
|
+
//[cite: 2]
|
|
281
378
|
ttfb: metrics.avgTtfbMs,
|
|
379
|
+
//[cite: 2]
|
|
282
380
|
dns: metrics.avgDnsMs,
|
|
381
|
+
//[cite: 2]
|
|
283
382
|
tcp: metrics.avgTcpMs,
|
|
383
|
+
//[cite: 2]
|
|
284
384
|
tls: metrics.avgTlsMs,
|
|
385
|
+
//[cite: 2]
|
|
285
386
|
stdDev: metrics.stdDevMs
|
|
387
|
+
//[cite: 2]
|
|
286
388
|
};
|
|
287
389
|
const isPassed = metrics.apdexScore >= config.targetApdex && metrics.errorRate <= config.targetErrorRate;
|
|
288
390
|
const verdictReason = isPassed ? "Static single-wave baseline checks concluded successfully without triggering health boundaries." : "Static verification loop completed with values exceeding defined quality thresholds.";
|
|
289
391
|
exportHtmlDashboard(history, config, verdictReason, semanticReport, {
|
|
392
|
+
//[cite: 2]
|
|
290
393
|
total2xx: metrics.c2xx,
|
|
291
394
|
total3xx: metrics.c3xx,
|
|
292
395
|
total4xx: metrics.c4xx,
|
|
293
396
|
total5xx: metrics.c5xx
|
|
397
|
+
//[cite: 2]
|
|
294
398
|
}, finalSummaryCards);
|
|
295
399
|
}
|
|
296
400
|
function generateSimulationData(threads, durationSec, maxAllowedLatencyMs) {
|
|
@@ -301,9 +405,13 @@ function generateSimulationData(threads, durationSec, maxAllowedLatencyMs) {
|
|
|
301
405
|
const isBreached = threads > targetThresholdBreak;
|
|
302
406
|
const stressFactor = isBreached ? Math.pow(threads / targetThresholdBreak, 1.5) : 1;
|
|
303
407
|
const errorPool = [
|
|
408
|
+
//[cite: 2]
|
|
304
409
|
`Error: ECONNREFUSED 127.0.0.1:5432 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1605:16)`,
|
|
410
|
+
//[cite: 2]
|
|
305
411
|
`HTTP/1.1 504 Gateway Timeout on POST /api/v1/checkout - upstream socket drop after 15000ms`,
|
|
412
|
+
//[cite: 2]
|
|
306
413
|
`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]
|
|
307
415
|
];
|
|
308
416
|
for (let i = 0; i < totalRequests; i++) {
|
|
309
417
|
const isError = Math.random() < (isBreached ? 0.05 : 1e-3);
|
|
@@ -315,13 +423,21 @@ function generateSimulationData(threads, durationSec, maxAllowedLatencyMs) {
|
|
|
315
423
|
errorMessage = `[${(/* @__PURE__ */ new Date()).toISOString()}] ` + errorPool[Math.floor(Math.random() * errorPool.length)];
|
|
316
424
|
}
|
|
317
425
|
data.push({
|
|
426
|
+
//[cite: 2]
|
|
318
427
|
durationMs: isError ? baseLatency * 0.1 : baseLatency,
|
|
428
|
+
//[cite: 2]
|
|
319
429
|
timestampMs: startTime + Math.random() * (durationSec * 1e3),
|
|
430
|
+
//[cite: 2]
|
|
320
431
|
dnsTimeMs: 1 + Math.random() * 0.9,
|
|
432
|
+
//[cite: 2]
|
|
321
433
|
tcpTimeMs: 4 + Math.random() * 1.5,
|
|
434
|
+
//[cite: 2]
|
|
322
435
|
tlsTimeMs: 6 + Math.random() * 1.8,
|
|
436
|
+
//[cite: 2]
|
|
323
437
|
statusCode,
|
|
438
|
+
//[cite: 2]
|
|
324
439
|
errorMessage
|
|
440
|
+
//[cite: 2]
|
|
325
441
|
});
|
|
326
442
|
}
|
|
327
443
|
return data.sort((a, b) => a.timestampMs - b.timestampMs);
|
|
@@ -351,22 +467,32 @@ function processMetricsTelemetry(requests, durationSec) {
|
|
|
351
467
|
const apdexScore = totalRequests === 0 ? 0 : (satisfied + tolerating / 2) / totalRequests;
|
|
352
468
|
const bandwidthMb = totalRequests * 1.2 / durationSec / 10;
|
|
353
469
|
return {
|
|
470
|
+
//[cite: 2]
|
|
354
471
|
totalRequests,
|
|
472
|
+
//[cite: 2]
|
|
355
473
|
requestsPerSecond: totalRequests / durationSec,
|
|
474
|
+
//[cite: 2]
|
|
356
475
|
avgLatencyMs,
|
|
476
|
+
//[cite: 2]
|
|
357
477
|
stdDevMs,
|
|
478
|
+
//[cite: 2]
|
|
358
479
|
p95LatencyMs,
|
|
480
|
+
//[cite: 2]
|
|
359
481
|
errorRate,
|
|
482
|
+
//[cite: 2]
|
|
360
483
|
apdexScore,
|
|
484
|
+
//[cite: 2]
|
|
361
485
|
c2xx,
|
|
362
486
|
c3xx,
|
|
363
487
|
c4xx,
|
|
364
488
|
c5xx,
|
|
489
|
+
//[cite: 2]
|
|
365
490
|
avgDnsMs,
|
|
366
491
|
avgTcpMs,
|
|
367
492
|
avgTlsMs,
|
|
368
493
|
avgTtfbMs,
|
|
369
494
|
bandwidthMb
|
|
495
|
+
//[cite: 2]
|
|
370
496
|
};
|
|
371
497
|
}
|
|
372
498
|
function printMatrixDashboard(m, threads) {
|
|
@@ -438,11 +564,9 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
438
564
|
<span style="background: ${sevBg}; color: #ffffff; padding: 0.2rem 0.5rem; border-radius: 4px; font-size: 0.7rem; font-weight: bold; letter-spacing: 0.05em;">${c.severity}</span>
|
|
439
565
|
</td>
|
|
440
566
|
<td style="padding: 1.25rem 0.75rem;">
|
|
441
|
-
<!-- Abstract Template Blueprint Box -->
|
|
442
567
|
<div style="background: #090d16; border-radius: 4px; padding: 0.6rem 0.8rem; border-left: 3px solid #1e293b; margin-bottom: 0.5rem;">
|
|
443
568
|
<code style="color: #cbd5e1; font-family: monospace; font-size: 0.9rem; white-space: pre-wrap; word-break: break-all;">${cleanedTemplate}</code>
|
|
444
569
|
</div>
|
|
445
|
-
<!-- Trace Example Line -->
|
|
446
570
|
<div style="color: #64748b; font-size: 0.8rem; font-family: monospace; padding-left: 0.2rem; line-height: 1.4;">
|
|
447
571
|
<span style="color: #475569;">Real Example Trace:</span> ${rawTemplate}
|
|
448
572
|
</div>
|
|
@@ -464,7 +588,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
464
588
|
h1 { color: #38bdf8; margin: 0; font-size: 2rem; }
|
|
465
589
|
.meta { color: #94a3b8; font-size: 0.9rem; margin-top: 0.5rem; }
|
|
466
590
|
|
|
467
|
-
/* \u{1F3B4} CARDS DASHBOARD GRID SYSTEM */
|
|
468
591
|
.cards-wrapper { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 1.5rem; }
|
|
469
592
|
.metric-card { background: #131c2e; border: 1px solid #1e293b; border-radius: 6px; padding: 1.25rem; position: relative; }
|
|
470
593
|
.card-title { font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.5rem; }
|
|
@@ -494,8 +617,10 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
494
617
|
.badge-5xx { background: rgba(220, 38, 38, 0.2); color: #f87171; }
|
|
495
618
|
.matrix-value { font-size: 1rem; font-weight: bold; color: #ffffff; }
|
|
496
619
|
|
|
497
|
-
|
|
498
|
-
.
|
|
620
|
+
/* \u{1F4CA} TWO-COLUMN CHART GRID */
|
|
621
|
+
.charts-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin-bottom: 2rem; }
|
|
622
|
+
.graph-card { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.5rem; }
|
|
623
|
+
.graph-title { font-size: 1.1rem; font-weight: 700; color: #ffffff; margin-bottom: 1.2rem; display: flex; align-items: center; gap: 0.5rem; }
|
|
499
624
|
|
|
500
625
|
.card { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.5rem; }
|
|
501
626
|
h3 { margin-top: 0; color: #cbd5e1; border-bottom: 1px solid #1e293b; padding-bottom: 0.5rem; }
|
|
@@ -512,7 +637,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
512
637
|
<div class="meta">Target Script: <code>${config.targetScript}</code></div>
|
|
513
638
|
</div>
|
|
514
639
|
|
|
515
|
-
<!-- \u{1F3B4} METRICS CARDS GRID PANEL -->
|
|
516
640
|
<div class="cards-wrapper">
|
|
517
641
|
<div class="metric-card">
|
|
518
642
|
<div class="card-title">Apdex Score (T: 50ms)</div>
|
|
@@ -576,11 +700,22 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
576
700
|
</div>
|
|
577
701
|
</div>
|
|
578
702
|
|
|
579
|
-
<!-- \u{1F4C9}
|
|
580
|
-
<div class="
|
|
581
|
-
|
|
582
|
-
<div
|
|
583
|
-
<
|
|
703
|
+
<!-- \u{1F4C9} SPLIT CHARTS SYSTEM -->
|
|
704
|
+
<div class="charts-grid">
|
|
705
|
+
<!-- Chart 1: Volume Streams -->
|
|
706
|
+
<div class="graph-card">
|
|
707
|
+
<div class="graph-title">\u{1F4CA} Throughput Velocity & Workload Volume</div>
|
|
708
|
+
<div style="height: 280px; position: relative;">
|
|
709
|
+
<canvas id="volumeChart"></canvas>
|
|
710
|
+
</div>
|
|
711
|
+
</div>
|
|
712
|
+
|
|
713
|
+
<!-- Chart 2: Concurrency & Health Trends -->
|
|
714
|
+
<div class="graph-card">
|
|
715
|
+
<div class="graph-title">\u{1F504} Active Concurrency (VUs) vs. Time-to-Failure (TTF) Trend</div>
|
|
716
|
+
<div style="height: 280px; position: relative;">
|
|
717
|
+
<canvas id="concurrencyChart"></canvas>
|
|
718
|
+
</div>
|
|
584
719
|
</div>
|
|
585
720
|
</div>
|
|
586
721
|
|
|
@@ -617,7 +752,9 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
617
752
|
|
|
618
753
|
<script>
|
|
619
754
|
const labels = ${JSON.stringify(labels)};
|
|
620
|
-
|
|
755
|
+
|
|
756
|
+
// \u{1F6E0}\uFE0F Chart 1 Setup: Throughput Bar Streams
|
|
757
|
+
new Chart(document.getElementById('volumeChart'), {
|
|
621
758
|
type: 'bar',
|
|
622
759
|
data: {
|
|
623
760
|
labels: labels,
|
|
@@ -637,25 +774,45 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
637
774
|
stack: 'requests',
|
|
638
775
|
barPercentage: 0.95,
|
|
639
776
|
categoryPercentage: 0.95
|
|
640
|
-
}
|
|
777
|
+
}
|
|
778
|
+
]
|
|
779
|
+
},
|
|
780
|
+
options: {
|
|
781
|
+
responsive: true,
|
|
782
|
+
maintainAspectRatio: false,
|
|
783
|
+
plugins: {
|
|
784
|
+
legend: { position: 'top', labels: { color: '#94a3b8', font: { size: 11 } } }
|
|
785
|
+
},
|
|
786
|
+
scales: {
|
|
787
|
+
x: { grid: { color: '#1e293b' }, ticks: { color: '#64748b' } },
|
|
788
|
+
y: { stacked: true, grid: { color: '#1e293b' }, ticks: { color: '#64748b' } }
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
// \u{1F6E0}\uFE0F Chart 2 Setup: Concurrency & TTF Correlated Slopes
|
|
794
|
+
new Chart(document.getElementById('concurrencyChart'), {
|
|
795
|
+
type: 'line',
|
|
796
|
+
data: {
|
|
797
|
+
labels: labels,
|
|
798
|
+
datasets: [
|
|
641
799
|
{
|
|
642
800
|
label: 'Active VU Threads',
|
|
643
801
|
data: ${JSON.stringify(activeThreadsData)},
|
|
644
|
-
type: 'line',
|
|
645
802
|
borderColor: '#38bdf8',
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
803
|
+
backgroundColor: 'rgba(56, 189, 248, 0.1)',
|
|
804
|
+
borderWidth: 2.5,
|
|
805
|
+
pointRadius: 4,
|
|
806
|
+
fill: true,
|
|
649
807
|
yAxisID: 'yThreads'
|
|
650
808
|
},
|
|
651
809
|
{
|
|
652
810
|
label: 'Time-to-Failure (TTF) Trend',
|
|
653
811
|
data: ${JSON.stringify(ttfTrendData)},
|
|
654
|
-
type: 'line',
|
|
655
812
|
borderColor: '#f43f5e',
|
|
656
|
-
borderWidth:
|
|
657
|
-
borderDash: [
|
|
658
|
-
pointRadius:
|
|
813
|
+
borderWidth: 2,
|
|
814
|
+
borderDash: [5, 5],
|
|
815
|
+
pointRadius: 3,
|
|
659
816
|
fill: false,
|
|
660
817
|
yAxisID: 'yTtf'
|
|
661
818
|
}
|
|
@@ -665,17 +822,13 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
665
822
|
responsive: true,
|
|
666
823
|
maintainAspectRatio: false,
|
|
667
824
|
plugins: {
|
|
668
|
-
legend: {
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
}
|
|
825
|
+
legend: { position: 'top', labels: { color: '#94a3b8', font: { size: 11 } } }
|
|
826
|
+
},
|
|
827
|
+
scales: {
|
|
828
|
+
x: { grid: { color: '#1e293b' }, ticks: { color: '#64748b' } },
|
|
829
|
+
y_threads: { position: 'left', grid: { color: '#1e293b' }, ticks: { color: '#38bdf8' }, title: { display: true, text: 'VUs / Threads', color: '#38bdf8' } },
|
|
830
|
+
y_ttf: { position: 'right', grid: { drawOnChartArea: false }, ticks: { color: '#f43f5e' }, title: { display: true, text: 'TTF Index / Latency ms', color: '#f43f5e' } }
|
|
672
831
|
}
|
|
673
|
-
},
|
|
674
|
-
scales: {
|
|
675
|
-
x: { grid: { color: '#1e293b' }, ticks: { color: '#64748b' } },
|
|
676
|
-
y: { stacked: true, grid: { color: '#1e293b' }, ticks: { color: '#64748b' }, title: { display: true, text: 'Requests Volume', color: '#64748b' } },
|
|
677
|
-
yThreads: { position: 'right', display: true, grid: { drawOnChartArea: false }, ticks: { color: '#38bdf8' }, title: { display: true, text: 'Active Threads', color: '#38bdf8' } },
|
|
678
|
-
yTtf: { position: 'right', display: false, grid: { drawOnChartArea: false } }
|
|
679
832
|
}
|
|
680
833
|
});
|
|
681
834
|
</script></body></html>`;
|
|
@@ -689,6 +842,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
689
842
|
function printUsage() {
|
|
690
843
|
console.log(`Blaze Core Performance Test CLI Engine
|
|
691
844
|
Options:
|
|
692
|
-
--threads <count> | --duration <seconds> | --agentic | --cluster-logs`);
|
|
845
|
+
--threads <count> | --duration <seconds> | --agentic | --cluster-logs | --correlate`);
|
|
693
846
|
}
|
|
694
847
|
main().catch(console.error);
|
|
Binary file
|