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 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 metrics = processMetricsTelemetry(rawRequests, config.durationSec);
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
- verdictReason = "The primary breakdown point was identified due to infrastructure saturation where throughput flattened while latency spiked rapidly.";
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blaze-performance-tester",
3
- "version": "3.0.31",
3
+ "version": "3.0.33",
4
4
  "description": "A high-performance, multi-threaded load testing engine built with Rust and QuickJS.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",