blaze-performance-tester 3.0.31 → 3.0.33
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 +76 -5
- package/dist/index.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -139,7 +139,7 @@ function parseArguments(args) {
|
|
|
139
139
|
const targetScript = path.resolve(args[0] || ".");
|
|
140
140
|
const isAgentic = args.includes("--agentic");
|
|
141
141
|
const isCorrelate = args.includes("--correlate");
|
|
142
|
-
const clusterLogs = args.includes("--cluster-logs");
|
|
142
|
+
const clusterLogs = !args.includes("--no-cluster-logs");
|
|
143
143
|
let threads = 10;
|
|
144
144
|
let durationSec = 10;
|
|
145
145
|
let targetApdex = 0.85;
|
|
@@ -205,7 +205,9 @@ async function runBlazeCoreEngine(config) {
|
|
|
205
205
|
if (!rawRequests || rawRequests.length === 0) {
|
|
206
206
|
rawRequests = generateSimulationData(config.threads, config.durationSec, config.maxAllowedLatencyMs);
|
|
207
207
|
}
|
|
208
|
-
const
|
|
208
|
+
const warmUpCutoff = Math.floor(rawRequests.length * 0.1);
|
|
209
|
+
const steadyStateRequests = rawRequests.slice(warmUpCutoff);
|
|
210
|
+
const metrics = processMetricsTelemetry(steadyStateRequests.length > 0 ? steadyStateRequests : rawRequests, config.durationSec);
|
|
209
211
|
const rawErrors = rawRequests.filter((r) => r.errorMessage).map((r) => r.errorMessage);
|
|
210
212
|
resolve2({ metrics, rawErrors });
|
|
211
213
|
}, 1e3);
|
|
@@ -221,6 +223,7 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
221
223
|
let baseStep = config.stepSize;
|
|
222
224
|
let isStable = true;
|
|
223
225
|
let verdictReason = "The system successfully scaled and remained stable within parameters up to maximum configured capacity allocations.";
|
|
226
|
+
let saturationKneePoint = null;
|
|
224
227
|
while (currentThreads <= config.maxThreads && isStable) {
|
|
225
228
|
console.log(`\u{1F916} [Agent Decision]: Testing execution tier at ${currentThreads} concurrent threads...`);
|
|
226
229
|
const { metrics, rawErrors } = await runBlazeCoreEngine({ ...config, threads: currentThreads });
|
|
@@ -254,7 +257,8 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
254
257
|
const previous = history[history.length - 2];
|
|
255
258
|
const dLatency_dThreads = (current.avgLatency - previous.avgLatency) / (current.threads - previous.threads);
|
|
256
259
|
if (current.throughput <= previous.throughput * 1.02 && dLatency_dThreads > 4.5) {
|
|
257
|
-
|
|
260
|
+
saturationKneePoint = currentThreads;
|
|
261
|
+
verdictReason = `Saturation knee-point identified at ${currentThreads} VUs where throughput flattened while latency spiked rapidly.`;
|
|
258
262
|
isStable = false;
|
|
259
263
|
break;
|
|
260
264
|
}
|
|
@@ -294,7 +298,8 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
294
298
|
dns: mathUtils.mean(globalMetricsAccumulator.dns),
|
|
295
299
|
tcp: mathUtils.mean(globalMetricsAccumulator.tcp),
|
|
296
300
|
tls: mathUtils.mean(globalMetricsAccumulator.tls),
|
|
297
|
-
stdDev: mathUtils.stdDev(globalMetricsAccumulator.latencies, mathUtils.mean(globalMetricsAccumulator.latencies))
|
|
301
|
+
stdDev: mathUtils.stdDev(globalMetricsAccumulator.latencies, mathUtils.mean(globalMetricsAccumulator.latencies)),
|
|
302
|
+
saturationKneePoint: saturationKneePoint || history[history.length - 1]?.threads || 50
|
|
298
303
|
};
|
|
299
304
|
generateFinalAgentReport(history);
|
|
300
305
|
exportHtmlDashboard(history, config, verdictReason, semanticReport, { total2xx, total3xx, total4xx, total5xx }, finalSummaryCards);
|
|
@@ -328,7 +333,8 @@ async function runStandardStressTest(config) {
|
|
|
328
333
|
dns: metrics.avgDnsMs,
|
|
329
334
|
tcp: metrics.avgTcpMs,
|
|
330
335
|
tls: metrics.avgTlsMs,
|
|
331
|
-
stdDev: metrics.stdDevMs
|
|
336
|
+
stdDev: metrics.stdDevMs,
|
|
337
|
+
saturationKneePoint: config.threads
|
|
332
338
|
};
|
|
333
339
|
const isPassed = metrics.apdexScore >= config.targetApdex && metrics.errorRate <= config.targetErrorRate;
|
|
334
340
|
const verdictReason = isPassed ? "Static single-wave baseline checks concluded successfully without triggering health boundaries." : "Static verification loop completed with values exceeding defined quality thresholds.";
|
|
@@ -453,6 +459,9 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
453
459
|
const waveListItems = history.map((h) => {
|
|
454
460
|
return `<div class="wave-item">Wave (${h.threads} VUs): P95 ${h.p95Latency.toFixed(1)}ms, Errors ${(h.errorRate * 100).toFixed(1)}%</div>`;
|
|
455
461
|
}).join("");
|
|
462
|
+
const estimatedMonthlyCost = (cards.throughput * 0.045 * 24 * 30).toFixed(2);
|
|
463
|
+
const recommendedCpuCores = Math.max(2, Math.ceil(cards.saturationKneePoint / 75));
|
|
464
|
+
const recommendedRamGb = recommendedCpuCores * 2;
|
|
456
465
|
let logClustersHtml = "";
|
|
457
466
|
if (semanticReport) {
|
|
458
467
|
const totalLogCount = semanticReport.clusters.reduce((sum, c) => sum + c.count, 0);
|
|
@@ -505,6 +514,50 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
505
514
|
</table>
|
|
506
515
|
</div>`;
|
|
507
516
|
}
|
|
517
|
+
const liveAdjusterHtml = `
|
|
518
|
+
<div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
|
|
519
|
+
<h3 style="color: #38bdf8; display: flex; align-items: center; gap: 0.5rem; font-size: 1.2rem; margin-bottom: 1rem;">
|
|
520
|
+
\u{1F39B}\uFE0F Live Concurrency Adjuster (Mid-Test Simulation)
|
|
521
|
+
</h3>
|
|
522
|
+
<div style="display: flex; gap: 2rem; align-items: center; flex-wrap: wrap;">
|
|
523
|
+
<div style="flex: 1; min-width: 280px;">
|
|
524
|
+
<label for="concurrencySlider" style="display: block; font-size: 0.85rem; color: #94a3b8; margin-bottom: 0.5rem;">
|
|
525
|
+
Scale Virtual Users (VUs): <strong id="sliderValue" style="color: #38bdf8;">${config.threads}</strong> threads
|
|
526
|
+
</label>
|
|
527
|
+
<input type="range" id="concurrencySlider" min="5" max="${config.maxThreads || 300}" step="5" value="${config.threads}" style="width: 100%; accent-color: #38bdf8; cursor: pointer;">
|
|
528
|
+
</div>
|
|
529
|
+
<div style="display: flex; gap: 1.5rem; text-align: center;">
|
|
530
|
+
<div style="background: #090d16; padding: 0.75rem 1rem; border-radius: 6px; border: 1px solid #1e293b;">
|
|
531
|
+
<div style="font-size: 0.7rem; color: #64748b; text-transform: uppercase;">Sim. Throughput</div>
|
|
532
|
+
<div id="simThroughput" style="font-size: 1.2rem; font-weight: bold; color: #f97316;">${cards.throughput.toFixed(0)}/s</div>
|
|
533
|
+
</div>
|
|
534
|
+
<div style="background: #090d16; padding: 0.75rem 1rem; border-radius: 6px; border: 1px solid #1e293b;">
|
|
535
|
+
<div style="font-size: 0.7rem; color: #64748b; text-transform: uppercase;">Sim. Latency</div>
|
|
536
|
+
<div id="simLatency" style="font-size: 1.2rem; font-weight: bold; color: #10b981;">${cards.ttfb.toFixed(1)}ms</div>
|
|
537
|
+
</div>
|
|
538
|
+
</div>
|
|
539
|
+
</div>
|
|
540
|
+
</div>`;
|
|
541
|
+
const rightSizingHtml = `
|
|
542
|
+
<div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
|
|
543
|
+
<h3 style="color: #38bdf8; display: flex; align-items: center; gap: 0.5rem; font-size: 1.2rem;">
|
|
544
|
+
\u2601\uFE0F Infrastructure Right-Sizing & Cloud Cost Projections
|
|
545
|
+
</h3>
|
|
546
|
+
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-top: 1rem;">
|
|
547
|
+
<div style="background: #090d16; padding: 1rem; border-radius: 6px; border: 1px solid #1e293b;">
|
|
548
|
+
<div class="card-title">Est. Monthly Cloud Cost</div>
|
|
549
|
+
<div class="card-value green">$${estimatedMonthlyCost} <span class="unit">/mo</span></div>
|
|
550
|
+
</div>
|
|
551
|
+
<div style="background: #090d16; padding: 1rem; border-radius: 6px; border: 1px solid #1e293b;">
|
|
552
|
+
<div class="card-title">Recommended CPU Right-Sizing</div>
|
|
553
|
+
<div class="card-value purple">${recommendedCpuCores} <span class="unit">vCores</span></div>
|
|
554
|
+
</div>
|
|
555
|
+
<div style="background: #090d16; padding: 1rem; border-radius: 6px; border: 1px solid #1e293b;">
|
|
556
|
+
<div class="card-title">Recommended Memory Allocation</div>
|
|
557
|
+
<div class="card-value orange">${recommendedRamGb} <span class="unit">GB RAM</span></div>
|
|
558
|
+
</div>
|
|
559
|
+
</div>
|
|
560
|
+
</div>`;
|
|
508
561
|
const htmlContent = `<!DOCTYPE html><html lang="en"><head>
|
|
509
562
|
<meta charset="UTF-8">
|
|
510
563
|
<title>Blaze Core Performance Report</title>
|
|
@@ -671,11 +724,29 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
671
724
|
</tbody>
|
|
672
725
|
</table>
|
|
673
726
|
</div>
|
|
727
|
+
${liveAdjusterHtml}
|
|
728
|
+
${rightSizingHtml}
|
|
674
729
|
${logClustersHtml}
|
|
675
730
|
</div>
|
|
676
731
|
|
|
677
732
|
<script>
|
|
678
733
|
const labels = ${JSON.stringify(labels)};
|
|
734
|
+
const baseThroughput = ${cards.throughput};
|
|
735
|
+
const baseLatency = ${cards.ttfb};
|
|
736
|
+
|
|
737
|
+
// Live Concurrency Adjuster interactive client logic
|
|
738
|
+
const slider = document.getElementById('concurrencySlider');
|
|
739
|
+
const sliderVal = document.getElementById('sliderValue');
|
|
740
|
+
const simThroughput = document.getElementById('simThroughput');
|
|
741
|
+
const simLatency = document.getElementById('simLatency');
|
|
742
|
+
|
|
743
|
+
slider.addEventListener('input', (e) => {
|
|
744
|
+
const val = parseInt(e.target.value, 10);
|
|
745
|
+
sliderVal.textContent = val;
|
|
746
|
+
const factor = val / ${config.threads || 10};
|
|
747
|
+
simThroughput.textContent = (baseThroughput * Math.min(factor, 2.5)).toFixed(0) + '/s';
|
|
748
|
+
simLatency.textContent = (baseLatency * Math.pow(factor, 0.8)).toFixed(1) + 'ms';
|
|
749
|
+
});
|
|
679
750
|
|
|
680
751
|
new Chart(document.getElementById('volumeChart'), {
|
|
681
752
|
type: 'bar',
|
|
Binary file
|