blaze-performance-tester 3.0.34 → 3.0.37
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 +61 -14
- package/dist/index.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -209,7 +209,7 @@ async function runBlazeCoreEngine(config) {
|
|
|
209
209
|
const steadyStateRequests = rawRequests.slice(warmUpCutoff);
|
|
210
210
|
const metrics = processMetricsTelemetry(steadyStateRequests.length > 0 ? steadyStateRequests : rawRequests, config.durationSec);
|
|
211
211
|
const rawErrors = rawRequests.filter((r) => r.errorMessage).map((r) => r.errorMessage);
|
|
212
|
-
resolve2({ metrics, rawErrors });
|
|
212
|
+
resolve2({ metrics, rawErrors, rawRequests: steadyStateRequests.length > 0 ? steadyStateRequests : rawRequests });
|
|
213
213
|
}, 1e3);
|
|
214
214
|
});
|
|
215
215
|
}
|
|
@@ -217,7 +217,8 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
217
217
|
console.log("\u{1F680} Initializing Intelligent Autonomous Load Agent...");
|
|
218
218
|
const history = [];
|
|
219
219
|
let aggregateErrorLogs = [];
|
|
220
|
-
let
|
|
220
|
+
let lastRawRequests = [];
|
|
221
|
+
let total1xx = 0, total2xx = 0, total3xx = 0, total4xx = 0, total5xx = 0;
|
|
221
222
|
let globalMetricsAccumulator = { dns: [], tcp: [], tls: [], ttfb: [], latencies: [], bandwidths: [] };
|
|
222
223
|
let currentThreads = Math.min(config.maxThreads, Math.max(5, Math.floor(config.maxThreads * 0.2)));
|
|
223
224
|
let baseStep = config.stepSize;
|
|
@@ -226,10 +227,12 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
226
227
|
let saturationKneePoint = null;
|
|
227
228
|
while (currentThreads <= config.maxThreads && isStable) {
|
|
228
229
|
console.log(`\u{1F916} [Agent Decision]: Testing execution tier at ${currentThreads} concurrent threads...`);
|
|
229
|
-
const { metrics, rawErrors } = await runBlazeCoreEngine({ ...config, threads: currentThreads });
|
|
230
|
+
const { metrics, rawErrors, rawRequests } = await runBlazeCoreEngine({ ...config, threads: currentThreads });
|
|
230
231
|
if (config.clusterLogs) {
|
|
231
232
|
aggregateErrorLogs = aggregateErrorLogs.concat(rawErrors);
|
|
232
233
|
}
|
|
234
|
+
lastRawRequests = rawRequests;
|
|
235
|
+
total1xx += metrics.c1xx;
|
|
233
236
|
total2xx += metrics.c2xx;
|
|
234
237
|
total3xx += metrics.c3xx;
|
|
235
238
|
total4xx += metrics.c4xx;
|
|
@@ -302,11 +305,11 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
302
305
|
saturationKneePoint: saturationKneePoint || history[history.length - 1]?.threads || 50
|
|
303
306
|
};
|
|
304
307
|
generateFinalAgentReport(history);
|
|
305
|
-
exportHtmlDashboard(history, config, verdictReason, semanticReport, { total2xx, total3xx, total4xx, total5xx }, finalSummaryCards);
|
|
308
|
+
exportHtmlDashboard(history, config, verdictReason, semanticReport, { total1xx, total2xx, total3xx, total4xx, total5xx }, finalSummaryCards, lastRawRequests);
|
|
306
309
|
}
|
|
307
310
|
async function runStandardStressTest(config) {
|
|
308
311
|
console.log(`\u{1F3CB}\uFE0F Running Standard Stress Test [Threads: ${config.threads} | Duration: ${config.durationSec}s]`);
|
|
309
|
-
const { metrics, rawErrors } = await runBlazeCoreEngine(config);
|
|
312
|
+
const { metrics, rawErrors, rawRequests } = await runBlazeCoreEngine(config);
|
|
310
313
|
printMatrixDashboard(metrics, config.threads);
|
|
311
314
|
const history = [{
|
|
312
315
|
threads: config.threads,
|
|
@@ -339,11 +342,12 @@ async function runStandardStressTest(config) {
|
|
|
339
342
|
const isPassed = metrics.apdexScore >= config.targetApdex && metrics.errorRate <= config.targetErrorRate;
|
|
340
343
|
const verdictReason = isPassed ? "Static single-wave baseline checks concluded successfully without triggering health boundaries." : "Static verification loop completed with values exceeding defined quality thresholds.";
|
|
341
344
|
exportHtmlDashboard(history, config, verdictReason, semanticReport, {
|
|
345
|
+
total1xx: metrics.c1xx,
|
|
342
346
|
total2xx: metrics.c2xx,
|
|
343
347
|
total3xx: metrics.c3xx,
|
|
344
348
|
total4xx: metrics.c4xx,
|
|
345
349
|
total5xx: metrics.c5xx
|
|
346
|
-
}, finalSummaryCards);
|
|
350
|
+
}, finalSummaryCards, rawRequests);
|
|
347
351
|
}
|
|
348
352
|
function getFallbackClusterLogs() {
|
|
349
353
|
const logs = [];
|
|
@@ -396,9 +400,10 @@ function processMetricsTelemetry(requests, durationSec) {
|
|
|
396
400
|
const avgTcpMs = mathUtils.mean(requests.map((r) => r.tcpTimeMs || 0));
|
|
397
401
|
const avgTlsMs = mathUtils.mean(requests.map((r) => r.tlsTimeMs || 0));
|
|
398
402
|
const avgTtfbMs = avgDnsMs + avgTcpMs + avgTlsMs + avgLatencyMs * 0.3;
|
|
399
|
-
let c2xx = 0, c3xx = 0, c4xx = 0, c5xx = 0;
|
|
403
|
+
let c1xx = 0, c2xx = 0, c3xx = 0, c4xx = 0, c5xx = 0;
|
|
400
404
|
requests.forEach((r) => {
|
|
401
|
-
if (r.statusCode >=
|
|
405
|
+
if (r.statusCode >= 100 && r.statusCode < 200) c1xx++;
|
|
406
|
+
else if (r.statusCode >= 200 && r.statusCode < 300) c2xx++;
|
|
402
407
|
else if (r.statusCode >= 300 && r.statusCode < 400) c3xx++;
|
|
403
408
|
else if (r.statusCode >= 400 && r.statusCode < 500) c4xx++;
|
|
404
409
|
else if (r.statusCode >= 500) c5xx++;
|
|
@@ -418,6 +423,7 @@ function processMetricsTelemetry(requests, durationSec) {
|
|
|
418
423
|
p95LatencyMs,
|
|
419
424
|
errorRate,
|
|
420
425
|
apdexScore,
|
|
426
|
+
c1xx,
|
|
421
427
|
c2xx,
|
|
422
428
|
c3xx,
|
|
423
429
|
c4xx,
|
|
@@ -450,7 +456,7 @@ function generateFinalAgentReport(history) {
|
|
|
450
456
|
console.log(`\u26A1 Peak Achieved Cluster Velocity : ${peakThroughput.toFixed(0)} req/sec`);
|
|
451
457
|
console.log("=======================================================\n");
|
|
452
458
|
}
|
|
453
|
-
function exportHtmlDashboard(history, config, verdictReason, semanticReport, responseMatrix, cards) {
|
|
459
|
+
function exportHtmlDashboard(history, config, verdictReason, semanticReport, responseMatrix, cards, rawRequests = []) {
|
|
454
460
|
const labels = history.map((h, i) => `${i + 1}s`);
|
|
455
461
|
const successRequestsData = history.map((h) => h.successRequests);
|
|
456
462
|
const failedWorkloadsData = history.map((h) => h.failedRequests);
|
|
@@ -462,6 +468,11 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
462
468
|
const estimatedMonthlyCost = (cards.throughput * 0.045 * 24 * 30).toFixed(2);
|
|
463
469
|
const recommendedCpuCores = Math.max(2, Math.ceil(cards.saturationKneePoint / 75));
|
|
464
470
|
const recommendedRamGb = recommendedCpuCores * 2;
|
|
471
|
+
const firstTimestamp = rawRequests[0]?.timestampMs || Date.now();
|
|
472
|
+
const scatterPoints = rawRequests.slice(0, 180).map((r) => ({
|
|
473
|
+
x: Number(((r.timestampMs - firstTimestamp) / 1e3).toFixed(2)),
|
|
474
|
+
y: Number(((r.dnsTimeMs || 0) + (r.tcpTimeMs || 0) + (r.tlsTimeMs || 0) + r.durationMs * 0.3).toFixed(1))
|
|
475
|
+
}));
|
|
465
476
|
let logClustersHtml = "";
|
|
466
477
|
if (semanticReport) {
|
|
467
478
|
const totalLogCount = semanticReport.clusters.reduce((sum, c) => sum + c.count, 0);
|
|
@@ -592,13 +603,14 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
592
603
|
.matrix-box .matrix-row:last-child { border-bottom: none; }
|
|
593
604
|
.matrix-label { font-size: 0.9rem; color: #f8fafc; display: flex; align-items: center; gap: 0.5rem; }
|
|
594
605
|
.matrix-badge { font-size: 0.7rem; font-weight: bold; padding: 0.1rem 0.3rem; border-radius: 4px; }
|
|
606
|
+
.badge-1xx { background: rgba(56, 189, 248, 0.2); color: #38bdf8; }
|
|
595
607
|
.badge-2xx { background: rgba(22, 163, 74, 0.2); color: #4ade80; }
|
|
596
608
|
.badge-3xx { background: rgba(148, 163, 184, 0.2); color: #cbd5e1; }
|
|
597
609
|
.badge-4xx { background: rgba(234, 179, 8, 0.2); color: #fde047; }
|
|
598
610
|
.badge-5xx { background: rgba(220, 38, 38, 0.2); color: #f87171; }
|
|
599
611
|
.matrix-value { font-size: 1rem; font-weight: bold; color: #ffffff; }
|
|
600
612
|
|
|
601
|
-
.charts-grid { display: grid; grid-template-columns: repeat(
|
|
613
|
+
.charts-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.5rem; margin-bottom: 2rem; }
|
|
602
614
|
.graph-card { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.5rem; }
|
|
603
615
|
.graph-title { font-size: 1.1rem; font-weight: 700; color: #ffffff; margin-bottom: 1.2rem; display: flex; align-items: center; gap: 0.5rem; }
|
|
604
616
|
|
|
@@ -661,6 +673,10 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
661
673
|
|
|
662
674
|
<div class="matrix-box">
|
|
663
675
|
<div class="matrix-title">\u{1F4CB} HTTP Response Matrix</div>
|
|
676
|
+
<div class="matrix-row">
|
|
677
|
+
<div class="matrix-label">Informational <span class="matrix-badge badge-1xx">1xx</span></div>
|
|
678
|
+
<div class="matrix-value">${responseMatrix.total1xx}</div>
|
|
679
|
+
</div>
|
|
664
680
|
<div class="matrix-row">
|
|
665
681
|
<div class="matrix-label">Successful <span class="matrix-badge badge-2xx">2xx</span></div>
|
|
666
682
|
<div class="matrix-value">${responseMatrix.total2xx}</div>
|
|
@@ -701,6 +717,13 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
701
717
|
<canvas id="statusDonutChart"></canvas>
|
|
702
718
|
</div>
|
|
703
719
|
</div>
|
|
720
|
+
|
|
721
|
+
<div class="graph-card">
|
|
722
|
+
<div class="graph-title">\u{1F4C8} Time-to-First-Byte Scatter Plot</div>
|
|
723
|
+
<div style="height: 280px; position: relative;">
|
|
724
|
+
<canvas id="ttfbScatterChart"></canvas>
|
|
725
|
+
</div>
|
|
726
|
+
</div>
|
|
704
727
|
</div>
|
|
705
728
|
|
|
706
729
|
<div class="card">
|
|
@@ -741,7 +764,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
741
764
|
const baseThroughput = ${cards.throughput};
|
|
742
765
|
const baseLatency = ${cards.ttfb};
|
|
743
766
|
|
|
744
|
-
// Live Concurrency Adjuster interactive client logic
|
|
767
|
+
// Live Concurrency Adjuster interactive client logic
|
|
745
768
|
const slider = document.getElementById('concurrencySlider');
|
|
746
769
|
const sliderVal = document.getElementById('sliderValue');
|
|
747
770
|
const simThroughput = document.getElementById('simThroughput');
|
|
@@ -835,10 +858,10 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
835
858
|
new Chart(document.getElementById('statusDonutChart'), {
|
|
836
859
|
type: 'doughnut',
|
|
837
860
|
data: {
|
|
838
|
-
labels: ['2xx Success', '3xx Redirect', '4xx Client Err', '5xx Server Err'],
|
|
861
|
+
labels: ['1xx Info', '2xx Success', '3xx Redirect', '4xx Client Err', '5xx Server Err'],
|
|
839
862
|
datasets: [{
|
|
840
|
-
data: [${responseMatrix.total2xx}, ${responseMatrix.total3xx}, ${responseMatrix.total4xx}, ${responseMatrix.total5xx}],
|
|
841
|
-
backgroundColor: ['#4ade80', '#cbd5e1', '#fde047', '#f87171'],
|
|
863
|
+
data: [${responseMatrix.total1xx}, ${responseMatrix.total2xx}, ${responseMatrix.total3xx}, ${responseMatrix.total4xx}, ${responseMatrix.total5xx}],
|
|
864
|
+
backgroundColor: ['#38bdf8', '#4ade80', '#cbd5e1', '#fde047', '#f87171'],
|
|
842
865
|
borderWidth: 1,
|
|
843
866
|
borderColor: '#1e293b'
|
|
844
867
|
}]
|
|
@@ -852,6 +875,30 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
852
875
|
cutout: '65%'
|
|
853
876
|
}
|
|
854
877
|
});
|
|
878
|
+
|
|
879
|
+
new Chart(document.getElementById('ttfbScatterChart'), {
|
|
880
|
+
type: 'scatter',
|
|
881
|
+
data: {
|
|
882
|
+
datasets: [{
|
|
883
|
+
label: 'Request Processing Delay',
|
|
884
|
+
data: ${JSON.stringify(scatterPoints)},
|
|
885
|
+
backgroundColor: '#a855f7',
|
|
886
|
+
pointRadius: 4,
|
|
887
|
+
pointHoverRadius: 6
|
|
888
|
+
}]
|
|
889
|
+
},
|
|
890
|
+
options: {
|
|
891
|
+
responsive: true,
|
|
892
|
+
maintainAspectRatio: false,
|
|
893
|
+
plugins: {
|
|
894
|
+
legend: { position: 'top', labels: { color: '#94a3b8', font: { size: 11 } } }
|
|
895
|
+
},
|
|
896
|
+
scales: {
|
|
897
|
+
x: { grid: { color: '#1e293b' }, ticks: { color: '#64748b' }, title: { display: true, text: 'Time offset (s)', color: '#64748b' } },
|
|
898
|
+
y: { grid: { color: '#1e293b' }, ticks: { color: '#64748b' }, title: { display: true, text: 'TTFB / Delay (ms)', color: '#64748b' } }
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
});
|
|
855
902
|
</script></body></html>`;
|
|
856
903
|
try {
|
|
857
904
|
fs.writeFileSync(config.outputHtml, htmlContent, "utf-8");
|
|
Binary file
|