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 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 total2xx = 0, total3xx = 0, total4xx = 0, total5xx = 0;
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 >= 200 && r.statusCode < 300) c2xx++;
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(3, 1fr); gap: 1.5rem; margin-bottom: 2rem; }
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[cite: 1]
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blaze-performance-tester",
3
- "version": "3.0.34",
3
+ "version": "3.0.37",
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",