blaze-performance-tester 3.1.24 → 3.1.26

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
@@ -467,7 +467,7 @@ function processMetricsTelemetry(requests, durationSec) {
467
467
  const avgTlsMs = mathUtils.mean(requests.map((r) => r.tlsTimeMs || 0));
468
468
  const avgTtfbMs = avgDnsMs + avgTcpMs + avgTlsMs + avgLatencyMs * 0.3;
469
469
  let c1xx = 0, c2xx = 0, c3xx = 0, c4xx = 0, c5xx = 0;
470
- const codeCounts = { 400: 0, 401: 0, 403: 0, 404: 429, 429: 0, 500: 0, 502: 0, 503: 0, 504: 0 };
470
+ const codeCounts = { 400: 0, 401: 0, 403: 0, 404: 0, 429: 0, 500: 0, 502: 0, 503: 0, 504: 0 };
471
471
  requests.forEach((r) => {
472
472
  if (r.statusCode >= 100 && r.statusCode < 200) c1xx++;
473
473
  else if (r.statusCode >= 200 && r.statusCode < 300) c2xx++;
@@ -540,6 +540,26 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
540
540
  const estimatedMonthlyCost = (cards.throughput * 0.045 * 24 * 30).toFixed(2);
541
541
  const recommendedCpuCores = Math.max(2, Math.ceil(cards.saturationKneePoint / 75));
542
542
  const recommendedRamGb = recommendedCpuCores * 2;
543
+ const rightSizingHtml = `
544
+ <div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
545
+ <h3 style="color: #a855f7; display: flex; align-items: center; gap: 0.5rem; font-size: 1.2rem; margin-bottom: 1rem; border-bottom: 1px solid #1e293b; padding-bottom: 0.5rem;">
546
+ \u{1F5A5}\uFE0F Infrastructure Right-Sizing & Cloud Cost Optimization
547
+ </h3>
548
+ <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;">
549
+ <div style="background: #090d16; padding: 1.25rem; border-radius: 6px; border: 1px solid #1e293b; text-align: center;">
550
+ <div class="card-title" style="color: #94a3b8;">Recommended Compute</div>
551
+ <div style="font-size: 1.75rem; font-weight: bold; color: #a855f7; margin-top: 0.4rem;">${recommendedCpuCores} Cores</div>
552
+ </div>
553
+ <div style="background: #090d16; padding: 1.25rem; border-radius: 6px; border: 1px solid #1e293b; text-align: center;">
554
+ <div class="card-title" style="color: #94a3b8;">Recommended Memory</div>
555
+ <div style="font-size: 1.75rem; font-weight: bold; color: #a855f7; margin-top: 0.4rem;">${recommendedRamGb} GB RAM</div>
556
+ </div>
557
+ <div style="background: #090d16; padding: 1.25rem; border-radius: 6px; border: 1px solid #1e293b; text-align: center;">
558
+ <div class="card-title" style="color: #94a3b8;">Est. Scale Cost / Month</div>
559
+ <div style="font-size: 1.75rem; font-weight: bold; color: #10b981; margin-top: 0.4rem;">$${estimatedMonthlyCost}</div>
560
+ </div>
561
+ </div>
562
+ </div>`;
543
563
  const firstTimestamp = rawRequests[0]?.timestampMs || Date.now();
544
564
  const scatterPoints = rawRequests.slice(0, 180).map((r) => ({
545
565
  x: Number(((r.timestampMs - firstTimestamp) / 1e3).toFixed(2)),
@@ -550,7 +570,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
550
570
  const totalLogCount = semanticReport.clusters.reduce((sum, c) => sum + c.count, 0);
551
571
  const uniquePatternsCount = semanticReport.clusters.length;
552
572
  logClustersHtml = `
553
- <div class="card p-dev" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
573
+ <div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
554
574
  <h3 style="border-bottom: none; padding-bottom: 0rem; margin-bottom: 0.25rem; display: flex; align-items: center; gap: 0.5rem; color: #ffffff; font-size: 1.2rem;">
555
575
  \u{1F9E0} Semantic Log Clustering & Error Classification
556
576
  </h3>
@@ -598,7 +618,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
598
618
  const finalLatency = history[history.length - 1]?.avgLatency || cards.ttfb;
599
619
  const seoMetrics = calculateSeoImpactMetrics(finalLatency);
600
620
  seoImpactSectionHtml = `
601
- <div class="card p-exec" style="margin-top: 2rem; background: #111a2e; border: 1px solid #1e3a8a;">
621
+ <div class="card" style="margin-top: 2rem; background: #111a2e; border: 1px solid #1e3a8a;">
602
622
  <h3 style="color: #f43f5e; display: flex; align-items: center; gap: 0.6rem; font-size: 1.2rem; border-bottom: 1px solid #1e293b; padding-bottom: 0.5rem;">
603
623
  \u{1F50E} SEO Rank Impact & Visibility Loss Predictor
604
624
  </h3>
@@ -621,7 +641,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
621
641
  </div>`;
622
642
  }
623
643
  const liveAdjusterHtml = `
624
- <div class="card p-devops" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
644
+ <div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
625
645
  <h3 style="color: #38bdf8; display: flex; align-items: center; gap: 0.5rem; font-size: 1.2rem; margin-bottom: 1rem;">
626
646
  \u{1F39B}\uFE0F Live Concurrency Adjuster (Mid-Test Simulation)
627
647
  </h3>
@@ -663,11 +683,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
663
683
  h1 { color: #38bdf8; margin: 0; font-size: 2rem; }
664
684
  .meta { color: #94a3b8; font-size: 0.9rem; margin-top: 0.5rem; }
665
685
 
666
- /* Persona Controls Styling */
667
- .persona-toggle-container { background: #131c2e; padding: 0.5rem 1rem; border-radius: 8px; border: 1px solid #1e293b; display: flex; align-items: center; gap: 0.75rem; }
668
- .persona-btn { background: #090d16; border: 1px solid #1e293b; color: #94a3b8; padding: 0.4rem 1rem; font-size: 0.85rem; font-weight: 600; border-radius: 6px; cursor: pointer; transition: all 0.2s ease; }
669
- .persona-btn.active { background: #38bdf8; border-color: #38bdf8; color: #0b111e; }
670
-
671
686
  .cards-wrapper { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 1.5rem; }
672
687
  .metric-card { background: #131c2e; border: 1px solid #1e293b; border-radius: 6px; padding: 1.25rem; position: relative; }
673
688
  .card-title { font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.5rem; }
@@ -720,59 +735,51 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
720
735
  <h1>\u{1F525} Blaze Core Performance Analysis</h1>
721
736
  <div class="meta">Target Script: <code>${config.targetScript}</code></div>
722
737
  </div>
723
-
724
- <!-- Persona View Switcher Selector Elements -->
725
- <div class="persona-toggle-container">
726
- <span style="font-size: 0.8rem; color: #64748b; font-weight: bold; text-transform: uppercase;">View Perspective:</span>
727
- <button class="persona-btn active" onclick="switchPersona('developer', this)">Developer</button>
728
- <button class="persona-btn" onclick="switchPersona('devops', this)">DevOps</button>
729
- <button class="persona-btn" onclick="switchPersona('executive', this)">Executive</button>
730
- </div>
731
738
  </div>
732
739
 
733
740
  <div class="cards-wrapper">
734
- <div class="metric-card p-dev">
741
+ <div class="metric-card">
735
742
  <div class="card-title">Apdex Score (T: 50ms)</div>
736
743
  <div class="card-value green">${cards.apdex.toFixed(2)}<span class="card-subtext">(Good)</span></div>
737
744
  </div>
738
- <div class="metric-card p-devops p-exec">
745
+ <div class="metric-card">
739
746
  <div class="card-title">Throughput</div>
740
747
  <div class="card-value orange">${cards.throughput.toFixed(1)}<span class="unit">/s</span></div>
741
748
  </div>
742
- <div class="metric-card p-devops">
749
+ <div class="metric-card">
743
750
  <div class="card-title">Network Bandwidth</div>
744
751
  <div class="card-value purple">${cards.bandwidth.toFixed(2)}<span class="unit">MB/s</span></div>
745
752
  </div>
746
- <div class="metric-card p-devops">
753
+ <div class="metric-card">
747
754
  <div class="card-title">Avg Time To First Byte</div>
748
755
  <div class="card-value">${cards.ttfb.toFixed(1)}<span class="unit">ms</span></div>
749
756
  </div>
750
- <div class="metric-card p-dev">
757
+ <div class="metric-card">
751
758
  <div class="card-title">DNS Lookup</div>
752
759
  <div class="card-value">${cards.dns.toFixed(2)}<span class="unit">ms</span></div>
753
760
  </div>
754
- <div class="metric-card p-dev">
761
+ <div class="metric-card">
755
762
  <div class="card-title">TCP Connect</div>
756
763
  <div class="card-value">${cards.tcp.toFixed(2)}<span class="unit">ms</span></div>
757
764
  </div>
758
- <div class="metric-card p-dev">
765
+ <div class="metric-card">
759
766
  <div class="card-title">TLS Handshake</div>
760
767
  <div class="card-value">${cards.tls.toFixed(2)}<span class="unit">ms</span></div>
761
768
  </div>
762
- <div class="metric-card p-dev p-exec">
769
+ <div class="metric-card">
763
770
  <div class="card-title">Stability (Std Dev)</div>
764
771
  <div class="card-value">&plusmn;${cards.stdDev.toFixed(1)}<span class="unit">ms</span></div>
765
772
  </div>
766
773
  </div>
767
774
 
768
775
  <div class="top-layout-grid">
769
- <div class="verdict-box p-devops p-exec">
776
+ <div class="verdict-box">
770
777
  <div class="verdict-title">\u{1F916} AI Stress-Testing Agent Verdict</div>
771
778
  <div class="verdict-text">${verdictReason}</div>
772
779
  <div class="verdict-waves">${waveListItems}</div>
773
780
  </div>
774
781
 
775
- <div class="gauge-container-box p-exec p-devops">
782
+ <div class="gauge-container-box">
776
783
  <div class="gauge-title">Blaze Run Health Score</div>
777
784
  <div style="position: relative; width: 140px; height: 140px; display: flex; align-items: center; justify-content: center;">
778
785
  <svg width="140" height="140" viewBox="0 0 140 140" style="transform: rotate(-90deg);">
@@ -788,7 +795,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
788
795
  </div>
789
796
  </div>
790
797
 
791
- <div class="matrix-box p-devops p-dev">
798
+ <div class="matrix-box">
792
799
  <div>
793
800
  <div class="matrix-title">\u{1F4CB} HTTP Response Matrix</div>
794
801
  <div class="matrix-row">
@@ -817,28 +824,28 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
817
824
  </div>
818
825
 
819
826
  <div class="charts-grid">
820
- <div class="graph-card p-devops">
827
+ <div class="graph-card">
821
828
  <div class="graph-title">\u{1F4CA} Throughput Velocity & Workload Volume</div>
822
829
  <div style="height: 280px; position: relative;">
823
830
  <canvas id="volumeChart"></canvas>
824
831
  </div>
825
832
  </div>
826
833
 
827
- <div class="graph-card p-devops">
834
+ <div class="graph-card">
828
835
  <div class="graph-title">\u{1F504} Active Concurrency (VUs) vs. TTF Trend</div>
829
836
  <div style="height: 280px; position: relative;">
830
837
  <canvas id="concurrencyChart"></canvas>
831
838
  </div>
832
839
  </div>
833
840
 
834
- <div class="graph-card p-dev">
841
+ <div class="graph-card">
835
842
  <div class="graph-title">\u{1F369} HTTP Status Code Proportions</div>
836
843
  <div style="height: 280px; position: relative;">
837
844
  <canvas id="statusDonutChart"></canvas>
838
845
  </div>
839
846
  </div>
840
847
 
841
- <div class="graph-card p-dev">
848
+ <div class="graph-card">
842
849
  <div class="graph-title">\u{1F4C8} Time-to-First-Byte Scatter Plot</div>
843
850
  <div style="height: 280px; position: relative;">
844
851
  <canvas id="ttfbScatterChart"></canvas>
@@ -846,7 +853,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
846
853
  </div>
847
854
  </div>
848
855
 
849
- <div class="card p-dev">
856
+ <div class="card">
850
857
  <h3>Telemetry Matrix Logs</h3>
851
858
  <table>
852
859
  <thead>
@@ -894,39 +901,8 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
894
901
  simThroughput.textContent = (baseThroughput * Math.min(factor, 2.5)).toFixed(0) + '/s';
895
902
  });
896
903
  }
897
-
898
- // Global register tracking charts for explicit redraw logic execution
899
- const activeCharts = [];
900
-
901
- function switchPersona(persona, targetBtn) {
902
- if (targetBtn) {
903
- document.querySelectorAll('.persona-btn').forEach(btn => btn.classList.remove('active'));
904
- targetBtn.classList.add('active');
905
- }
906
-
907
- // Hide all dynamic viewport configurations
908
- const layouts = ['.p-dev', '.p-devops', '.p-exec'];
909
- layouts.forEach(selector => {
910
- document.querySelectorAll(selector).forEach(el => el.style.display = 'none');
911
- });
912
-
913
- // Target current selector views for block visibility execution
914
- document.querySelectorAll('.p-' + persona).forEach(el => {
915
- if (el.tagName === 'TR') el.style.display = 'table-row';
916
- else if (el.classList.contains('metric-card')) el.style.display = 'block';
917
- else el.style.display = '';
918
- });
919
-
920
- // AUTO-REFRESH IMPLEMENTATION: Triggers sizing layout re-calculations on unhidden canvases
921
- activeCharts.forEach(chart => {
922
- if (chart) {
923
- chart.resize();
924
- chart.update('active');
925
- }
926
- });
927
- }
928
904
 
929
- activeCharts.push(new Chart(document.getElementById('volumeChart'), {
905
+ new Chart(document.getElementById('volumeChart'), {
930
906
  type: 'bar',
931
907
  data: {
932
908
  labels: labels,
@@ -936,9 +912,9 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
936
912
  ]
937
913
  },
938
914
  options: { responsive: true, maintainAspectRatio: false, scales: { x: { grid: { color: '#1e293b' } }, y: { stacked: true, grid: { color: '#1e293b' } } } }
939
- }));
915
+ });
940
916
 
941
- activeCharts.push(new Chart(document.getElementById('concurrencyChart'), {
917
+ new Chart(document.getElementById('concurrencyChart'), {
942
918
  type: 'line',
943
919
  data: {
944
920
  labels: labels,
@@ -948,26 +924,22 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
948
924
  ]
949
925
  },
950
926
  options: { responsive: true, maintainAspectRatio: false }
951
- }));
927
+ });
952
928
 
953
- activeCharts.push(new Chart(document.getElementById('statusDonutChart'), {
929
+ new Chart(document.getElementById('statusDonutChart'), {
954
930
  type: 'doughnut',
955
931
  data: {
956
932
  labels: ['Success', 'Client Err', 'Server Err'],
957
933
  datasets: [{ data: [${responseMatrix.total2xx}, ${responseMatrix.total4xx}, ${responseMatrix.total5xx}], backgroundColor: ['#4ade80', '#fde047', '#f87171'] }]
958
934
  },
959
935
  options: { responsive: true, maintainAspectRatio: false }
960
- }));
936
+ });
961
937
 
962
- activeCharts.push(new Chart(document.getElementById('ttfbScatterChart'), {
938
+ new Chart(document.getElementById('ttfbScatterChart'), {
963
939
  type: 'scatter',
964
940
  data: { datasets: [{ label: 'Processing Delay', data: ${JSON.stringify(scatterPoints)}, backgroundColor: '#a855f7' }] },
965
941
  options: { responsive: true, maintainAspectRatio: false }
966
- }));
967
-
968
- // Bootstrapped configuration state defaults dashboard load view to Developer
969
- document.querySelectorAll('.p-devops, .p-exec').forEach(el => el.style.display = 'none');
970
- document.querySelectorAll('.p-dev').forEach(el => el.style.display = '');
942
+ });
971
943
  </script></body></html>`;
972
944
  try {
973
945
  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.1.24",
3
+ "version": "3.1.26",
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",