blaze-performance-tester 3.1.13 → 3.1.14

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,9 +85,7 @@ 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
- },
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])
88
+ }
91
89
  };
92
90
  async function executeTestPipeline(config) {
93
91
  if (!blazeCore || typeof blazeCore.runCorrelatedTransaction !== "function") {
@@ -141,7 +139,6 @@ function parseArguments(args) {
141
139
  const targetScript = path.resolve(args[0] || ".");
142
140
  const isAgentic = args.includes("--agentic");
143
141
  const isCorrelate = args.includes("--correlate");
144
- const isSeoEnabled = args.includes("--seo");
145
142
  const clusterLogs = !args.includes("--no-cluster-logs");
146
143
  let threads = 10;
147
144
  let durationSec = 10;
@@ -187,7 +184,6 @@ function parseArguments(args) {
187
184
  targetScript,
188
185
  isAgentic,
189
186
  isCorrelate,
190
- isSeoEnabled,
191
187
  clusterLogs,
192
188
  threads,
193
189
  durationSec,
@@ -266,8 +262,6 @@ async function runIntelligentAgenticStressTest(config) {
266
262
  threads: currentThreads,
267
263
  avgLatency: metrics.avgLatencyMs,
268
264
  p95Latency: metrics.p95LatencyMs,
269
- minLatency: metrics.minLatencyMs,
270
- maxLatency: metrics.maxLatencyMs,
271
265
  errorRate: metrics.errorRate,
272
266
  apdex: metrics.apdexScore,
273
267
  throughput: metrics.requestsPerSecond,
@@ -343,9 +337,7 @@ async function runIntelligentAgenticStressTest(config) {
343
337
  cls: mathUtils.mean(globalMetricsAccumulator.cls),
344
338
  econnresetRate: totalGlobalRequests === 0 ? 0 : totalEconnreset / totalGlobalRequests * 100,
345
339
  econnrefusedCount: totalEconnrefused,
346
- codeRates: aggregatedCodeRates,
347
- minLatency: history.length === 0 ? 0 : Math.min(...history.map((h) => h.minLatency)),
348
- maxLatency: history.length === 0 ? 0 : Math.max(...history.map((h) => h.maxLatency))
340
+ codeRates: aggregatedCodeRates
349
341
  };
350
342
  generateFinalAgentReport(history);
351
343
  exportHtmlDashboard(history, config, verdictReason, semanticReport, { total1xx, total2xx, total3xx, total4xx, total5xx }, finalSummaryCards, lastRawRequests);
@@ -358,8 +350,6 @@ async function runStandardStressTest(config) {
358
350
  threads: config.threads,
359
351
  avgLatency: metrics.avgLatencyMs,
360
352
  p95Latency: metrics.p95LatencyMs,
361
- minLatency: metrics.minLatencyMs,
362
- maxLatency: metrics.maxLatencyMs,
363
353
  errorRate: metrics.errorRate,
364
354
  apdex: metrics.apdexScore,
365
355
  throughput: metrics.requestsPerSecond,
@@ -395,9 +385,7 @@ async function runStandardStressTest(config) {
395
385
  cls: metrics.clsScore,
396
386
  econnresetRate: metrics.econnresetRate,
397
387
  econnrefusedCount: metrics.econnrefusedCount,
398
- codeRates: metrics.codeRates,
399
- minLatency: metrics.minLatencyMs,
400
- maxLatency: metrics.maxLatencyMs
388
+ codeRates: metrics.codeRates
401
389
  };
402
390
  const isPassed = metrics.apdexScore >= config.targetApdex && metrics.errorRate <= config.targetErrorRate;
403
391
  const verdictReason = isPassed ? "Static single-wave baseline checks concluded successfully without triggering health boundaries." : "Static verification loop completed with values exceeding defined quality thresholds.";
@@ -451,7 +439,7 @@ function generateSimulationData(threads, durationSec, maxAllowedLatencyMs) {
451
439
  if (Math.random() < 0.03) statusCode = 302;
452
440
  }
453
441
  data.push({
454
- durationMs: isError ? baseLatency * 0.1 + 2 : baseLatency + Math.random() * 20,
442
+ durationMs: isError ? baseLatency * 0.1 : baseLatency,
455
443
  timestampMs: startTime + Math.random() * (durationSec * 1e3),
456
444
  dnsTimeMs: 1 + Math.random() * 0.9,
457
445
  tcpTimeMs: 4 + Math.random() * 1.5,
@@ -468,8 +456,6 @@ function processMetricsTelemetry(requests, durationSec, apdexT) {
468
456
  const avgLatencyMs = mathUtils.mean(durations);
469
457
  const stdDevMs = mathUtils.stdDev(durations, avgLatencyMs);
470
458
  const p95LatencyMs = mathUtils.percentile(durations, 95);
471
- const minLatencyMs = mathUtils.min(durations);
472
- const maxLatencyMs = mathUtils.max(durations);
473
459
  const avgDnsMs = mathUtils.mean(requests.map((r) => r.dnsTimeMs || 0));
474
460
  const avgTcpMs = mathUtils.mean(requests.map((r) => r.tcpTimeMs || 0));
475
461
  const avgTlsMs = mathUtils.mean(requests.map((r) => r.tlsTimeMs || 0));
@@ -477,6 +463,7 @@ function processMetricsTelemetry(requests, durationSec, apdexT) {
477
463
  let c1xx = 0, c2xx = 0, c3xx = 0, c4xx = 0, c5xx = 0;
478
464
  let econnresetCount = 0;
479
465
  let econnrefusedCount = 0;
466
+ const targetCodes = [400, 401, 403, 404, 429, 500, 502, 503, 504];
480
467
  const codeCounts = { 400: 0, 401: 0, 403: 0, 404: 0, 429: 0, 500: 0, 502: 0, 503: 0, 504: 0 };
481
468
  requests.forEach((r) => {
482
469
  if (r.statusCode >= 100 && r.statusCode < 200) c1xx++;
@@ -493,7 +480,7 @@ function processMetricsTelemetry(requests, durationSec, apdexT) {
493
480
  }
494
481
  });
495
482
  const codeRates = {};
496
- Object.keys(codeCounts).forEach((code) => {
483
+ targetCodes.forEach((code) => {
497
484
  codeRates[code] = totalRequests === 0 ? 0 : codeCounts[code] / totalRequests * 100;
498
485
  });
499
486
  const econnresetRate = totalRequests === 0 ? 0 : econnresetCount / totalRequests * 100;
@@ -512,8 +499,6 @@ function processMetricsTelemetry(requests, durationSec, apdexT) {
512
499
  avgLatencyMs,
513
500
  stdDevMs,
514
501
  p95LatencyMs,
515
- minLatencyMs,
516
- maxLatencyMs,
517
502
  errorRate,
518
503
  apdexScore,
519
504
  c1xx,
@@ -543,7 +528,7 @@ function printMatrixDashboard(m, threads) {
543
528
  console.log(`-----------------------------------------------------------------------------------------`);
544
529
  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)} |`);
545
530
  console.log(`-----------------------------------------------------------------------------------------`);
546
- console.log(`| Network & Floor -> RESET: ${m.econnresetRate.toFixed(1)}% | Min/Max Boundary: ${m.minLatencyMs.toFixed(1)}ms / ${m.maxLatencyMs.toFixed(1)}ms`);
531
+ console.log(`| Network State -> RESET Rate: ${m.econnresetRate.toFixed(2)}% | REFUSED Count: ${m.econnrefusedCount} | Web Vitals -> LCP: ${m.lcpMs.toFixed(0)}ms |`);
547
532
  console.log(`-----------------------------------------------------------------------------------------`);
548
533
  }
549
534
  function generateFinalAgentReport(history) {
@@ -566,7 +551,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
566
551
  const activeThreadsData = history.map((h) => h.threads);
567
552
  const ttfTrendData = history.map((h) => h.avgLatency * 1.1);
568
553
  const waveListItems = history.map((h) => {
569
- 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>`;
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>`;
570
555
  }).join("");
571
556
  const estimatedMonthlyCost = (cards.throughput * 0.045 * 24 * 30).toFixed(2);
572
557
  const recommendedCpuCores = Math.max(2, Math.ceil(cards.saturationKneePoint / 75));
@@ -582,86 +567,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
582
567
  const lcpStat = getLcpStatus(cards.lcp);
583
568
  const fidStat = getFidStatus(cards.fid);
584
569
  const clsStat = getClsStatus(cards.cls);
585
- let seoPredictorPanelHtml = "";
586
- if (config.isSeoEnabled) {
587
- const lcp = cards.lcp;
588
- let seoScore = 100;
589
- let visibilityLossPct = 0;
590
- let trafficDropPct = 0;
591
- let rankDropPositions = 0;
592
- if (lcp > 2500) {
593
- if (lcp <= 4e3) {
594
- const ratio = (lcp - 2500) / 1500;
595
- seoScore = 100 - ratio * 30;
596
- visibilityLossPct = ratio * 14.5;
597
- trafficDropPct = ratio * 18.2;
598
- rankDropPositions = Number((ratio * 1.2).toFixed(1));
599
- } else {
600
- const ratio = Math.min(1, (lcp - 4e3) / 4e3);
601
- seoScore = Math.max(8, 70 - ratio * 62);
602
- visibilityLossPct = 14.5 + ratio * 52;
603
- trafficDropPct = 18.2 + ratio * 58.5;
604
- rankDropPositions = Number((1.2 + ratio * 4.6).toFixed(1));
605
- }
606
- }
607
- let seoColor = "#10b981";
608
- let seoStatus = "EXCELLENT";
609
- if (seoScore < 90) {
610
- seoColor = "#f59e0b";
611
- seoStatus = "NEEDS IMPROVEMENT";
612
- }
613
- if (seoScore < 60) {
614
- seoColor = "#ef4444";
615
- seoStatus = "CRITICAL RISK / PENALIZED";
616
- }
617
- seoPredictorPanelHtml = `
618
- <div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
619
- <h3 style="color: #38bdf8; font-size: 1.2rem; border-bottom: none; margin-bottom: 0.25rem;">
620
- \u{1F50D} Google SEO Rank & Search Visibility Impact Predictor
621
- </h3>
622
- <div style="color: #94a3b8; font-size: 0.9rem; margin-bottom: 1.5rem;">
623
- Predictive algorithmic simulation modeling response degradation metrics directly against Google Core Web Vitals signal rules.
624
- </div>
625
-
626
- <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; flex-wrap: wrap;">
627
- <div style="background: #090d16; padding: 1.25rem; border-radius: 6px; border: 1px solid #1e293b; text-align: center;">
628
- <div style="font-size: 0.75rem; color: #64748b; text-transform: uppercase; font-weight: bold;">Core Web Vitals SEO Score</div>
629
- <div style="font-size: 1.8rem; font-weight: bold; color: ${seoColor}; margin-top: 0.25rem;">
630
- ${seoScore.toFixed(0)}<span style="font-size: 1rem; color: #94a3b8;">/100</span>
631
- </div>
632
- <div style="font-size: 0.75rem; font-weight: bold; margin-top: 0.4rem; color: ${seoColor};">${seoStatus}</div>
633
- </div>
634
-
635
- <div style="background: #090d16; padding: 1.25rem; border-radius: 6px; border: 1px solid #1e293b; text-align: center;">
636
- <div style="font-size: 0.75rem; color: #64748b; text-transform: uppercase; font-weight: bold;">Search Visibility Loss</div>
637
- <div style="font-size: 1.8rem; font-weight: bold; color: ${visibilityLossPct > 0 ? "#ef4444" : "#10b981"}; margin-top: 0.25rem;">
638
- -${visibilityLossPct.toFixed(1)}%
639
- </div>
640
- <div style="font-size: 0.75rem; color: #64748b; margin-top: 0.4rem;">Projected SERP Impression Drop</div>
641
- </div>
642
-
643
- <div style="background: #090d16; padding: 1.25rem; border-radius: 6px; border: 1px solid #1e293b; text-align: center;">
644
- <div style="font-size: 1.8rem; font-weight: bold; color: ${trafficDropPct > 0 ? "#ef4444" : "#10b981"}; margin-top: 0.25rem;">
645
- -${trafficDropPct.toFixed(1)}%
646
- </div>
647
- <div style="font-size: 0.75rem; color: #64748b; margin-top: 0.4rem;">Expected funnel volume drop</div>
648
- </div>
649
-
650
- <div style="background: #090d16; padding: 1.25rem; border-radius: 6px; border: 1px solid #1e293b; text-align: center;">
651
- <div style="font-size: 0.75rem; color: #64748b; text-transform: uppercase; font-weight: bold;">Avg SERP Position Shift</div>
652
- <div style="font-size: 1.8rem; font-weight: bold; color: ${rankDropPositions > 0 ? "#f59e0b" : "#10b981"}; margin-top: 0.25rem;">
653
- ${rankDropPositions > 0 ? `+${rankDropPositions}` : "0.0"}
654
- </div>
655
- <div style="font-size: 0.75rem; color: #64748b; margin-top: 0.4rem;">Rank places dropped down standard index</div>
656
- </div>
657
- </div>
658
-
659
- <div style="margin-top: 1rem; background: #090d16; padding: 1rem; border-radius: 6px; border: 1px solid #1e293b; font-size: 0.85rem; line-height: 1.5; color: #cbd5e1;">
660
- <strong>\u{1F52E} SEO Engine Intelligence Breakdown:</strong>
661
- ${lcp <= 2500 ? "Your simulated Largest Contentful Paint equivalent falls safely within Google's 'Good' range (&le; 2500ms). The parsing layer calculates zero performance-based rank penalties under current system load profiles." : lcp <= 4e3 ? `Warning: Current concurrency load has pushed LCP to ${lcp.toFixed(0)}ms, landing in Google's 'Needs Improvement' window. This response drag risks triggering index rank adjustments, potentially demoting listings down by ~${rankDropPositions} positions and sacrificing around ${trafficDropPct.toFixed(0)}% of organic top-of-funnel users.` : `Critical Signal Breach: Load performance has forced LCP to ${lcp.toFixed(0)}ms, severely violating Google's 'Poor' performance ceiling (&gt; 4000ms). At this level, ranking algorithms actively de-weight domains. Expect structural search visibility erosion up to ${visibilityLossPct.toFixed(0)}% and immediate organic traffic redirection.`}
662
- </div>
663
- </div>`;
664
- }
665
570
  const connectionDiagnosticsPanelHtml = `
666
571
  <div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
667
572
  <h3 style="color: #38bdf8; font-size: 1.2rem; border-bottom: none; margin-bottom: 0.25rem;">
@@ -839,8 +744,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
839
744
  .meta { color: #94a3b8; font-size: 0.9rem; margin-top: 0.5rem; }
840
745
 
841
746
  .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; }
842
- .cards-wrapper { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 1.5rem; }
843
- @media (max-width: 1024px) { .cards-wrapper { grid-template-columns: repeat(2, 1fr); } }
747
+ .cards-wrapper { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 1.5rem; }
844
748
  .metric-card { background: #131c2e; border: 1px solid #1e293b; border-radius: 6px; padding: 1.25rem; position: relative; }
845
749
  .card-title { font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.5rem; }
846
750
  .card-value { font-size: 1.6rem; font-weight: 700; color: #ffffff; }
@@ -849,7 +753,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
849
753
  .card-value.orange { color: #f97316; }
850
754
  .card-value.purple { color: #a855f7; }
851
755
  .card-value.cyan { color: #38bdf8; }
852
- .card-value.red { color: #f87171; }
853
756
  .card-subtext { font-size: 0.8rem; font-weight: 500; margin-left: 0.4rem; display: inline-block; }
854
757
  .card-subtext.green { color: #10b981; }
855
758
  .card-subtext.orange { color: #f97316; }
@@ -897,20 +800,12 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
897
800
  <div class="cards-wrapper">
898
801
  <div class="metric-card">
899
802
  <div class="card-title">Apdex Score (T: ${config.apdexT}ms)</div>
900
- <div class="card-value green">${cards.apdex.toFixed(2)}<span class="card-subtext green">(Verified)</span></div>
803
+ <div class="card-value green">${cards.apdex.toFixed(2)}<span class="card-subtext green">(Target Verified)</span></div>
901
804
  </div>
902
805
  <div class="metric-card">
903
806
  <div class="card-title">Throughput</div>
904
807
  <div class="card-value orange">${cards.throughput.toFixed(1)}<span class="unit">/s</span></div>
905
808
  </div>
906
- <div class="metric-card">
907
- <div class="card-title">Minimum Response Time</div>
908
- <div class="card-value green">${cards.minLatency.toFixed(1)}<span class="unit">ms</span></div>
909
- </div>
910
- <div class="metric-card">
911
- <div class="card-title">Maximum Response Time</div>
912
- <div class="card-value red">${cards.maxLatency.toFixed(1)}<span class="unit">ms</span></div>
913
- </div>
914
809
  <div class="metric-card">
915
810
  <div class="card-title">Network Bandwidth</div>
916
811
  <div class="card-value purple">${cards.bandwidth.toFixed(2)}<span class="unit">MB/s</span></div>
@@ -1017,8 +912,8 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1017
912
  <th>Throughput</th>
1018
913
  <th>Avg Latency</th>
1019
914
  <th>P95 Latency</th>
1020
- <th>Min / Max Floor</th>
1021
- <th>RESET Rate</th>
915
+ <th>ECONNRESET Rate</th>
916
+ <th>ECONNREFUSED</th>
1022
917
  <th>Status</th>
1023
918
  </tr>
1024
919
  </thead>
@@ -1030,15 +925,14 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1030
925
  <td>${h.throughput.toFixed(0)} req/sec</td>
1031
926
  <td>${h.avgLatency.toFixed(1)} ms</td>
1032
927
  <td>${h.p95Latency.toFixed(1)} ms</td>
1033
- <td><small>${h.minLatency.toFixed(1)}ms / ${h.maxLatency.toFixed(1)}ms</small></td>
1034
928
  <td>${h.econnresetRate.toFixed(2)}%</td>
929
+ <td>${h.econnrefusedCount} nodes</td>
1035
930
  <td><span class="badge ${isPassed ? "badge-success" : "badge-fail"}">${isPassed ? "SLO PASS" : "SLO BREACH"}</span></td>
1036
931
  </tr>`;
1037
932
  }).join("")}
1038
933
  </tbody>
1039
934
  </table>
1040
935
  </div>
1041
- ${seoPredictorPanelHtml}
1042
936
  ${connectionDiagnosticsPanelHtml}
1043
937
  ${liveAdjusterHtml}
1044
938
  ${rightSizingHtml}
@@ -1202,8 +1096,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1202
1096
  }
1203
1097
  }
1204
1098
  function printUsage() {
1205
- console.log(`Blaze Core Performance Test CLI Engine
1206
- Options:
1207
- --threads <count> | --duration <seconds> | --agentic | --cluster-logs | --correlate | --apdex-t <ms> | --seo`);
1099
+ console.log(`Blaze Core Performance Test CLI Engine\\nOptions:\\n --threads <count> | --duration <seconds> | --agentic | --cluster-logs | --correlate | --apdex-t <ms>`);
1208
1100
  }
1209
1101
  main().catch(console.error);
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blaze-performance-tester",
3
- "version": "3.1.13",
3
+ "version": "3.1.14",
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",