blaze-performance-tester 3.1.8 → 3.1.10

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
@@ -85,7 +85,9 @@ var mathUtils = {
85
85
  const sorted = [...arr].sort((a, b) => a - b);
86
86
  const index = Math.ceil(p / 100 * sorted.length) - 1;
87
87
  return sorted[Math.max(0, index)];
88
- }
88
+ },
89
+ min: (arr) => arr.length === 0 ? 0 : arr.reduce((min, val) => val < min ? val : min, arr[0]),
90
+ max: (arr) => arr.length === 0 ? 0 : arr.reduce((max, val) => val > max ? val : max, arr[0])
89
91
  };
90
92
  async function executeTestPipeline(config) {
91
93
  if (!blazeCore || typeof blazeCore.runCorrelatedTransaction !== "function") {
@@ -262,6 +264,8 @@ async function runIntelligentAgenticStressTest(config) {
262
264
  threads: currentThreads,
263
265
  avgLatency: metrics.avgLatencyMs,
264
266
  p95Latency: metrics.p95LatencyMs,
267
+ minLatency: metrics.minLatencyMs,
268
+ maxLatency: metrics.maxLatencyMs,
265
269
  errorRate: metrics.errorRate,
266
270
  apdex: metrics.apdexScore,
267
271
  throughput: metrics.requestsPerSecond,
@@ -337,7 +341,9 @@ async function runIntelligentAgenticStressTest(config) {
337
341
  cls: mathUtils.mean(globalMetricsAccumulator.cls),
338
342
  econnresetRate: totalGlobalRequests === 0 ? 0 : totalEconnreset / totalGlobalRequests * 100,
339
343
  econnrefusedCount: totalEconnrefused,
340
- codeRates: aggregatedCodeRates
344
+ codeRates: aggregatedCodeRates,
345
+ minLatency: history.length === 0 ? 0 : Math.min(...history.map((h) => h.minLatency)),
346
+ maxLatency: history.length === 0 ? 0 : Math.max(...history.map((h) => h.maxLatency))
341
347
  };
342
348
  generateFinalAgentReport(history);
343
349
  exportHtmlDashboard(history, config, verdictReason, semanticReport, { total1xx, total2xx, total3xx, total4xx, total5xx }, finalSummaryCards, lastRawRequests);
@@ -350,6 +356,8 @@ async function runStandardStressTest(config) {
350
356
  threads: config.threads,
351
357
  avgLatency: metrics.avgLatencyMs,
352
358
  p95Latency: metrics.p95LatencyMs,
359
+ minLatency: metrics.minLatencyMs,
360
+ maxLatency: metrics.maxLatencyMs,
353
361
  errorRate: metrics.errorRate,
354
362
  apdex: metrics.apdexScore,
355
363
  throughput: metrics.requestsPerSecond,
@@ -385,7 +393,9 @@ async function runStandardStressTest(config) {
385
393
  cls: metrics.clsScore,
386
394
  econnresetRate: metrics.econnresetRate,
387
395
  econnrefusedCount: metrics.econnrefusedCount,
388
- codeRates: metrics.codeRates
396
+ codeRates: metrics.codeRates,
397
+ minLatency: metrics.minLatencyMs,
398
+ maxLatency: metrics.maxLatencyMs
389
399
  };
390
400
  const isPassed = metrics.apdexScore >= config.targetApdex && metrics.errorRate <= config.targetErrorRate;
391
401
  const verdictReason = isPassed ? "Static single-wave baseline checks concluded successfully without triggering health boundaries." : "Static verification loop completed with values exceeding defined quality thresholds.";
@@ -439,7 +449,7 @@ function generateSimulationData(threads, durationSec, maxAllowedLatencyMs) {
439
449
  if (Math.random() < 0.03) statusCode = 302;
440
450
  }
441
451
  data.push({
442
- durationMs: isError ? baseLatency * 0.1 : baseLatency,
452
+ durationMs: isError ? baseLatency * 0.1 + 2 : baseLatency + Math.random() * 20,
443
453
  timestampMs: startTime + Math.random() * (durationSec * 1e3),
444
454
  dnsTimeMs: 1 + Math.random() * 0.9,
445
455
  tcpTimeMs: 4 + Math.random() * 1.5,
@@ -456,6 +466,8 @@ function processMetricsTelemetry(requests, durationSec, apdexT) {
456
466
  const avgLatencyMs = mathUtils.mean(durations);
457
467
  const stdDevMs = mathUtils.stdDev(durations, avgLatencyMs);
458
468
  const p95LatencyMs = mathUtils.percentile(durations, 95);
469
+ const minLatencyMs = mathUtils.min(durations);
470
+ const maxLatencyMs = mathUtils.max(durations);
459
471
  const avgDnsMs = mathUtils.mean(requests.map((r) => r.dnsTimeMs || 0));
460
472
  const avgTcpMs = mathUtils.mean(requests.map((r) => r.tcpTimeMs || 0));
461
473
  const avgTlsMs = mathUtils.mean(requests.map((r) => r.tlsTimeMs || 0));
@@ -499,6 +511,8 @@ function processMetricsTelemetry(requests, durationSec, apdexT) {
499
511
  avgLatencyMs,
500
512
  stdDevMs,
501
513
  p95LatencyMs,
514
+ minLatencyMs,
515
+ maxLatencyMs,
502
516
  errorRate,
503
517
  apdexScore,
504
518
  c1xx,
@@ -528,7 +542,7 @@ function printMatrixDashboard(m, threads) {
528
542
  console.log(`-----------------------------------------------------------------------------------------`);
529
543
  console.log(`| ${pad(threads, 7)} | ${pad(m.totalRequests, 9)} | ${pad(m.avgLatencyMs.toFixed(1) + "ms", 11)} | ${pad(m.p95LatencyMs.toFixed(1) + "ms", 11)} | ${pad(m.requestsPerSecond.toFixed(0) + "/s", 10)} | ${pad((m.errorRate * 100).toFixed(2) + "%", 10)} | ${pad(m.apdexScore.toFixed(2), 9)} |`);
530
544
  console.log(`-----------------------------------------------------------------------------------------`);
531
- console.log(`| Network State -> RESET Rate: ${m.econnresetRate.toFixed(2)}% | REFUSED Count: ${m.econnrefusedCount} | Web Vitals -> LCP: ${m.lcpMs.toFixed(0)}ms |`);
545
+ console.log(`| Network & Floor -> RESET: ${m.econnresetRate.toFixed(1)}% | Min/Max Boundary: ${m.minLatencyMs.toFixed(1)}ms / ${m.maxLatencyMs.toFixed(1)}ms`);
532
546
  console.log(`-----------------------------------------------------------------------------------------`);
533
547
  }
534
548
  function generateFinalAgentReport(history) {
@@ -551,7 +565,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
551
565
  const activeThreadsData = history.map((h) => h.threads);
552
566
  const ttfTrendData = history.map((h) => h.avgLatency * 1.1);
553
567
  const waveListItems = history.map((h) => {
554
- return `<div class="wave-item">Wave (${h.threads} VUs): P95 ${h.p95Latency.toFixed(1)}ms, ECONNRESET Rate: ${h.econnresetRate.toFixed(1)}%, REFUSED: ${h.econnrefusedCount}</div>`;
568
+ return `<div class="wave-item">Wave (${h.threads} VUs): Floor ${h.minLatency.toFixed(1)}ms | Ceil ${h.maxLatency.toFixed(1)}ms | P95 ${h.p95Latency.toFixed(1)}ms</div>`;
555
569
  }).join("");
556
570
  const estimatedMonthlyCost = (cards.throughput * 0.045 * 24 * 30).toFixed(2);
557
571
  const recommendedCpuCores = Math.max(2, Math.ceil(cards.saturationKneePoint / 75));
@@ -744,7 +758,8 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
744
758
  .meta { color: #94a3b8; font-size: 0.9rem; margin-top: 0.5rem; }
745
759
 
746
760
  .section-title { font-size: 1.2rem; color: #cbd5e1; font-weight: bold; margin: 2rem 0 1rem 0; padding-bottom: 0.4rem; border-bottom: 1px solid #1e293b; }
747
- .cards-wrapper { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 1.5rem; }
761
+ .cards-wrapper { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 1.5rem; }
762
+ @media (max-width: 1024px) { .cards-wrapper { grid-template-columns: repeat(2, 1fr); } }
748
763
  .metric-card { background: #131c2e; border: 1px solid #1e293b; border-radius: 6px; padding: 1.25rem; position: relative; }
749
764
  .card-title { font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.5rem; }
750
765
  .card-value { font-size: 1.6rem; font-weight: 700; color: #ffffff; }
@@ -753,6 +768,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
753
768
  .card-value.orange { color: #f97316; }
754
769
  .card-value.purple { color: #a855f7; }
755
770
  .card-value.cyan { color: #38bdf8; }
771
+ .card-value.red { color: #f87171; }
756
772
  .card-subtext { font-size: 0.8rem; font-weight: 500; margin-left: 0.4rem; display: inline-block; }
757
773
  .card-subtext.green { color: #10b981; }
758
774
  .card-subtext.orange { color: #f97316; }
@@ -800,12 +816,20 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
800
816
  <div class="cards-wrapper">
801
817
  <div class="metric-card">
802
818
  <div class="card-title">Apdex Score (T: ${config.apdexT}ms)</div>
803
- <div class="card-value green">${cards.apdex.toFixed(2)}<span class="card-subtext green">(Target Verified)</span></div>
819
+ <div class="card-value green">${cards.apdex.toFixed(2)}<span class="card-subtext green">(Verified)</span></div>
804
820
  </div>
805
821
  <div class="metric-card">
806
822
  <div class="card-title">Throughput</div>
807
823
  <div class="card-value orange">${cards.throughput.toFixed(1)}<span class="unit">/s</span></div>
808
824
  </div>
825
+ <div class="metric-card">
826
+ <div class="card-title">Minimum Response Time</div>
827
+ <div class="card-value green">${cards.minLatency.toFixed(1)}<span class="unit">ms</span></div>
828
+ </div>
829
+ <div class="metric-card">
830
+ <div class="card-title">Maximum Response Time</div>
831
+ <div class="card-value red">${cards.maxLatency.toFixed(1)}<span class="unit">ms</span></div>
832
+ </div>
809
833
  <div class="metric-card">
810
834
  <div class="card-title">Network Bandwidth</div>
811
835
  <div class="card-value purple">${cards.bandwidth.toFixed(2)}<span class="unit">MB/s</span></div>
@@ -912,8 +936,8 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
912
936
  <th>Throughput</th>
913
937
  <th>Avg Latency</th>
914
938
  <th>P95 Latency</th>
915
- <th>ECONNRESET Rate</th>
916
- <th>ECONNREFUSED</th>
939
+ <th>Min / Max Floor</th>
940
+ <th>RESET Rate</th>
917
941
  <th>Status</th>
918
942
  </tr>
919
943
  </thead>
@@ -925,8 +949,8 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
925
949
  <td>${h.throughput.toFixed(0)} req/sec</td>
926
950
  <td>${h.avgLatency.toFixed(1)} ms</td>
927
951
  <td>${h.p95Latency.toFixed(1)} ms</td>
952
+ <td><small>${h.minLatency.toFixed(1)}ms / ${h.maxLatency.toFixed(1)}ms</small></td>
928
953
  <td>${h.econnresetRate.toFixed(2)}%</td>
929
- <td>${h.econnrefusedCount} nodes</td>
930
954
  <td><span class="badge ${isPassed ? "badge-success" : "badge-fail"}">${isPassed ? "SLO PASS" : "SLO BREACH"}</span></td>
931
955
  </tr>`;
932
956
  }).join("")}
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blaze-performance-tester",
3
- "version": "3.1.8",
3
+ "version": "3.1.10",
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",