blaze-performance-tester 3.1.22 → 3.1.23

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: 0, 429: 0, 500: 502, 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++;
@@ -550,7 +550,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
550
550
  const totalLogCount = semanticReport.clusters.reduce((sum, c) => sum + c.count, 0);
551
551
  const uniquePatternsCount = semanticReport.clusters.length;
552
552
  logClustersHtml = `
553
- <div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
553
+ <div class="card p-dev" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
554
554
  <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
555
  \u{1F9E0} Semantic Log Clustering & Error Classification
556
556
  </h3>
@@ -564,7 +564,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
564
564
  <th style="width: 8%; padding: 0.75rem; text-align: left; color: #64748b; font-size: 0.85rem; font-weight: bold; text-transform: none;">Count</th>
565
565
  <th style="width: 22%; padding: 0.75rem; text-align: left; color: #64748b; font-size: 0.85rem; font-weight: bold; text-transform: none;">Classification Category</th>
566
566
  <th style="width: 10%; padding: 0.75rem; text-align: left; color: #64748b; font-size: 0.85rem; font-weight: bold; text-transform: none;">Severity</th>
567
- <th style="width: 60%; padding: 0.75rem; text-align: left; color: #64748b; font-size: 0.85rem; font-weight: bold; text-transform: none;">Structural Abstract Blueprint / Dynamic Log Fingerprint</th>
567
+ <th style="width: 60%; padding: 0.75rem; text-align: left; color: #64748b; font-size: 0.85rem; font-weight: bold; text-transform: none;">Structural Abstract Blueprint</th>
568
568
  </tr>
569
569
  </thead>
570
570
  <tbody>
@@ -572,7 +572,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
572
572
  let catColor = "#fb923c";
573
573
  if (c.category === "Authentication_Error") catColor = "#c084fc";
574
574
  if (c.category === "Product_Error") catColor = "#f87171";
575
- if (c.category === "Environment_Infrastructure_Error") catColor = "#fb923c";
576
575
  let sevBg = c.severity === "CRITICAL" ? "#dc2626" : "#ea580c";
577
576
  const rawTemplate = c.template || "";
578
577
  const cleanedTemplate = rawTemplate.replace(/\[\d{4}-\d{2}-\d{2}.*?\]\s*/, "");
@@ -587,9 +586,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
587
586
  <div style="background: #090d16; border-radius: 4px; padding: 0.6rem 0.8rem; border-left: 3px solid #1e293b; margin-bottom: 0.5rem;">
588
587
  <code style="color: #cbd5e1; font-family: monospace; font-size: 0.9rem; white-space: pre-wrap; word-break: break-all;">${cleanedTemplate}</code>
589
588
  </div>
590
- <div style="color: #64748b; font-size: 0.8rem; font-family: monospace; padding-left: 0.2rem; line-height: 1.4;">
591
- <span style="color: #475569;">Real Example Trace:</span> ${rawTemplate}
592
- </div>
593
589
  </td>
594
590
  </tr>`;
595
591
  }).join("")}
@@ -602,25 +598,20 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
602
598
  const finalLatency = history[history.length - 1]?.avgLatency || cards.ttfb;
603
599
  const seoMetrics = calculateSeoImpactMetrics(finalLatency);
604
600
  seoImpactSectionHtml = `
605
- <div class="card" style="margin-top: 2rem; background: #111a2e; border: 1px solid #1e3a8a;">
601
+ <div class="card p-exec" style="margin-top: 2rem; background: #111a2e; border: 1px solid #1e3a8a;">
606
602
  <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;">
607
603
  \u{1F50E} SEO Rank Impact & Visibility Loss Predictor
608
604
  </h3>
609
- <p style="color: #94a3b8; font-size: 0.9rem; margin-bottom: 1.5rem;">
610
- Translates response time infrastructure load stress into Core Web Vitals ranking drops and organic search volume degradation metrics.
611
- </p>
612
605
  <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;">
613
606
  <div style="background: #090d16; padding: 1.25rem; border-radius: 6px; border: 1px solid #1e293b; text-align: center;">
614
607
  <div class="card-title" style="color: #94a3b8;">Est. Organic Traffic Loss</div>
615
608
  <div style="font-size: 2rem; font-weight: bold; color: ${seoMetrics.color};">
616
609
  ${seoMetrics.trafficLoss > 0 ? "-" : ""}${seoMetrics.trafficLoss}%
617
610
  </div>
618
- <div style="font-size: 0.8rem; color: #64748b; margin-top: 0.25rem;">compared to 200ms sweet-spot</div>
619
611
  </div>
620
612
  <div style="background: #090d16; padding: 1.25rem; border-radius: 6px; border: 1px solid #1e293b;">
621
613
  <div class="card-title">Search Visibility Status</div>
622
614
  <div style="font-size: 1.25rem; font-weight: bold; color: ${seoMetrics.color}; margin-top: 0.4rem;">${seoMetrics.status}</div>
623
- <div style="font-size: 0.8rem; color: #94a3b8; margin-top: 0.25rem;">Target Latency: ${finalLatency.toFixed(1)}ms</div>
624
615
  </div>
625
616
  <div style="background: #090d16; padding: 1.25rem; border-radius: 6px; border: 1px solid #1e293b;">
626
617
  <div class="card-title">Googlebot Crawl Budget Impact</div>
@@ -630,7 +621,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
630
621
  </div>`;
631
622
  }
632
623
  const liveAdjusterHtml = `
633
- <div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
624
+ <div class="card p-devops" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
634
625
  <h3 style="color: #38bdf8; display: flex; align-items: center; gap: 0.5rem; font-size: 1.2rem; margin-bottom: 1rem;">
635
626
  \u{1F39B}\uFE0F Live Concurrency Adjuster (Mid-Test Simulation)
636
627
  </h3>
@@ -646,15 +637,11 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
646
637
  <div style="font-size: 0.7rem; color: #64748b; text-transform: uppercase;">Sim. Throughput</div>
647
638
  <div id="simThroughput" style="font-size: 1.2rem; font-weight: bold; color: #f97316;">${cards.throughput.toFixed(0)}/s</div>
648
639
  </div>
649
- <div style="background: #090d16; padding: 0.75rem 1rem; border-radius: 6px; border: 1px solid #1e293b;">
650
- <div style="font-size: 0.7rem; color: #64748b; text-transform: uppercase;">Sim. Latency</div>
651
- <div id="simLatency" style="font-size: 1.2rem; font-weight: bold; color: #10b981;">${cards.ttfb.toFixed(1)}ms</div>
652
- </div>
653
640
  </div>
654
641
  </div>
655
642
  </div>`;
656
643
  const rightSizingHtml = `
657
- <div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
644
+ <div class="card p-devops p-exec" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
658
645
  <h3 style="color: #38bdf8; display: flex; align-items: center; gap: 0.5rem; font-size: 1.2rem;">
659
646
  \u2601\uFE0F Infrastructure Right-Sizing & Cloud Cost Projections
660
647
  </h3>
@@ -692,10 +679,15 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
692
679
  <style>
693
680
  body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0b111e; color: #f8fafc; margin: 0; padding: 2rem; }
694
681
  .container { max-width: 1300px; margin: 0 auto; }
695
- .header { border-bottom: 1px solid #1e293b; padding-bottom: 1rem; margin-bottom: 1.5rem; }
682
+ .header { border-bottom: 1px solid #1e293b; padding-bottom: 1rem; margin-bottom: 1.5rem; display: flex; justify-content: space-between; align-items: center; }
696
683
  h1 { color: #38bdf8; margin: 0; font-size: 2rem; }
697
684
  .meta { color: #94a3b8; font-size: 0.9rem; margin-top: 0.5rem; }
698
685
 
686
+ /* Persona Controls Styling */
687
+ .persona-toggle-container { background: #131c2e; padding: 0.5rem 1rem; border-radius: 8px; border: 1px solid #1e293b; display: flex; align-items: center; gap: 0.75rem; }
688
+ .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; }
689
+ .persona-btn.active { background: #38bdf8; border-color: #38bdf8; color: #0b111e; }
690
+
699
691
  .cards-wrapper { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 1.5rem; }
700
692
  .metric-card { background: #131c2e; border: 1px solid #1e293b; border-radius: 6px; padding: 1.25rem; position: relative; }
701
693
  .card-title { font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.5rem; }
@@ -744,86 +736,84 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
744
736
  </style></head><body>
745
737
  <div class="container">
746
738
  <div class="header">
747
- <h1>\u{1F525} Blaze Core Performance Analysis</h1>
748
- <div class="meta">Target Script: <code>${config.targetScript}</code></div>
739
+ <div>
740
+ <h1>\u{1F525} Blaze Core Performance Analysis</h1>
741
+ <div class="meta">Target Script: <code>${config.targetScript}</code></div>
742
+ </div>
743
+
744
+ <!-- IMPLEMENTED: Persona Selector Toggle Buttons -->
745
+ <div class="persona-toggle-container">
746
+ <span style="font-size: 0.8rem; color: #64748b; font-weight: bold; text-transform: uppercase;">View Perspective:</span>
747
+ <button class="persona-btn active" onclick="switchPersona('developer')">Developer</button>
748
+ <button class="persona-btn" onclick="switchPersona('devops')">DevOps</button>
749
+ <button class="persona-btn" onclick="switchPersona('executive')">Executive</button>
750
+ </div>
749
751
  </div>
750
752
 
751
753
  <div class="cards-wrapper">
752
- <div class="metric-card">
754
+ <div class="metric-card p-dev">
753
755
  <div class="card-title">Apdex Score (T: 50ms)</div>
754
756
  <div class="card-value green">${cards.apdex.toFixed(2)}<span class="card-subtext">(Good)</span></div>
755
757
  </div>
756
- <div class="metric-card">
758
+ <div class="metric-card p-devops p-exec">
757
759
  <div class="card-title">Throughput</div>
758
760
  <div class="card-value orange">${cards.throughput.toFixed(1)}<span class="unit">/s</span></div>
759
761
  </div>
760
- <div class="metric-card">
762
+ <div class="metric-card p-devops">
761
763
  <div class="card-title">Network Bandwidth</div>
762
764
  <div class="card-value purple">${cards.bandwidth.toFixed(2)}<span class="unit">MB/s</span></div>
763
765
  </div>
764
- <div class="metric-card">
766
+ <div class="metric-card p-devops">
765
767
  <div class="card-title">Avg Time To First Byte</div>
766
768
  <div class="card-value">${cards.ttfb.toFixed(1)}<span class="unit">ms</span></div>
767
769
  </div>
768
- <div class="metric-card">
770
+ <div class="metric-card p-dev">
769
771
  <div class="card-title">DNS Lookup</div>
770
772
  <div class="card-value">${cards.dns.toFixed(2)}<span class="unit">ms</span></div>
771
773
  </div>
772
- <div class="metric-card">
774
+ <div class="metric-card p-dev">
773
775
  <div class="card-title">TCP Connect</div>
774
776
  <div class="card-value">${cards.tcp.toFixed(2)}<span class="unit">ms</span></div>
775
777
  </div>
776
- <div class="metric-card">
778
+ <div class="metric-card p-dev">
777
779
  <div class="card-title">TLS Handshake</div>
778
780
  <div class="card-value">${cards.tls.toFixed(2)}<span class="unit">ms</span></div>
779
781
  </div>
780
- <div class="metric-card">
782
+ <div class="metric-card p-dev p-exec">
781
783
  <div class="card-title">Stability (Std Dev)</div>
782
784
  <div class="card-value">&plusmn;${cards.stdDev.toFixed(1)}<span class="unit">ms</span></div>
783
785
  </div>
784
786
  </div>
785
787
 
786
788
  <div class="top-layout-grid">
787
- <div class="verdict-box">
789
+ <div class="verdict-box p-devops p-exec">
788
790
  <div class="verdict-title">\u{1F916} AI Stress-Testing Agent Verdict</div>
789
791
  <div class="verdict-text">${verdictReason}</div>
790
792
  <div class="verdict-waves">${waveListItems}</div>
791
793
  </div>
792
794
 
793
- <!-- IMPLEMENTED CARD FEATURE 76: Executive Health Gauges Panel -->
794
- <div class="gauge-container-box">
795
+ <div class="gauge-container-box p-exec p-devops">
795
796
  <div class="gauge-title">Blaze Run Health Score</div>
796
797
  <div style="position: relative; width: 140px; height: 140px; display: flex; align-items: center; justify-content: center;">
797
798
  <svg width="140" height="140" viewBox="0 0 140 140" style="transform: rotate(-90deg);">
798
799
  <circle cx="70" cy="70" r="58" stroke="#1e293b" stroke-width="12" fill="transparent"/>
799
800
  <circle cx="70" cy="70" r="58" stroke="${gaugeColor}" stroke-width="12" fill="transparent"
800
801
  stroke-dasharray="364.4" stroke-dashoffset="${364.4 - 364.4 * cards.healthScore / 100}"
801
- stroke-linecap="round" style="transition: stroke-dashoffset 1s ease-out;"/>
802
+ stroke-linecap="round"/>
802
803
  </svg>
803
804
  <div style="position: absolute; text-align: center;">
804
805
  <div style="font-size: 2.2rem; font-weight: 800; color: #ffffff; line-height: 1;">${cards.healthScore}</div>
805
806
  <div style="font-size: 0.75rem; color: #64748b; font-weight: bold; margin-top: 0.2rem; text-transform: uppercase;">/ 100</div>
806
807
  </div>
807
808
  </div>
808
- <div style="margin-top: 0.75rem; font-size: 0.8rem; color: #94a3b8; font-weight: 500;">
809
- Composite Run Quality Engine Rating
810
- </div>
811
809
  </div>
812
810
 
813
- <div class="matrix-box">
811
+ <div class="matrix-box p-devops p-dev">
814
812
  <div class="matrix-title">\u{1F4CB} HTTP Response Matrix</div>
815
- <div class="matrix-row">
816
- <div class="matrix-label">Informational <span class="matrix-badge badge-1xx">1xx</span></div>
817
- <div class="matrix-value">${responseMatrix.total1xx}</div>
818
- </div>
819
813
  <div class="matrix-row">
820
814
  <div class="matrix-label">Successful <span class="matrix-badge badge-2xx">2xx</span></div>
821
815
  <div class="matrix-value">${responseMatrix.total2xx}</div>
822
816
  </div>
823
- <div class="matrix-row">
824
- <div class="matrix-label">Redirects <span class="matrix-badge badge-3xx">3xx</span></div>
825
- <div class="matrix-value">${responseMatrix.total3xx}</div>
826
- </div>
827
817
  <div class="matrix-row">
828
818
  <div class="matrix-label">Client Error <span class="matrix-badge badge-4xx">4xx</span></div>
829
819
  <div class="matrix-value">${responseMatrix.total4xx}</div>
@@ -843,28 +833,28 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
843
833
  </div>
844
834
 
845
835
  <div class="charts-grid">
846
- <div class="graph-card">
836
+ <div class="graph-card p-devops">
847
837
  <div class="graph-title">\u{1F4CA} Throughput Velocity & Workload Volume</div>
848
838
  <div style="height: 280px; position: relative;">
849
839
  <canvas id="volumeChart"></canvas>
850
840
  </div>
851
841
  </div>
852
842
 
853
- <div class="graph-card">
843
+ <div class="graph-card p-devops">
854
844
  <div class="graph-title">\u{1F504} Active Concurrency (VUs) vs. TTF Trend</div>
855
845
  <div style="height: 280px; position: relative;">
856
846
  <canvas id="concurrencyChart"></canvas>
857
847
  </div>
858
848
  </div>
859
849
 
860
- <div class="graph-card">
850
+ <div class="graph-card p-dev">
861
851
  <div class="graph-title">\u{1F369} HTTP Status Code Proportions</div>
862
852
  <div style="height: 280px; position: relative;">
863
853
  <canvas id="statusDonutChart"></canvas>
864
854
  </div>
865
855
  </div>
866
856
 
867
- <div class="graph-card">
857
+ <div class="graph-card p-dev">
868
858
  <div class="graph-title">\u{1F4C8} Time-to-First-Byte Scatter Plot</div>
869
859
  <div style="height: 280px; position: relative;">
870
860
  <canvas id="ttfbScatterChart"></canvas>
@@ -872,7 +862,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
872
862
  </div>
873
863
  </div>
874
864
 
875
- <div class="card">
865
+ <div class="card p-dev">
876
866
  <h3>Telemetry Matrix Logs</h3>
877
867
  <table>
878
868
  <thead>
@@ -881,7 +871,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
881
871
  <th>Throughput</th>
882
872
  <th>Avg Latency</th>
883
873
  <th>P95 Latency</th>
884
- <th>Error Rate</th>
885
874
  <th>Status</th>
886
875
  </tr>
887
876
  </thead>
@@ -893,7 +882,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
893
882
  <td>${h.throughput.toFixed(0)} req/sec</td>
894
883
  <td>${h.avgLatency.toFixed(1)} ms</td>
895
884
  <td>${h.p95Latency.toFixed(1)} ms</td>
896
- <td>${(h.errorRate * 100).toFixed(2)}%</td>
897
885
  <td><span class="badge ${isPassed ? "badge-success" : "badge-fail"}">${isPassed ? "SLO PASS" : "SLO BREACH"}</span></td>
898
886
  </tr>`;
899
887
  }).join("")}
@@ -909,55 +897,49 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
909
897
  <script>
910
898
  const labels = ${JSON.stringify(labels)};
911
899
  const baseThroughput = ${cards.throughput};
912
- const baseLatency = ${cards.ttfb};
913
900
 
914
901
  const slider = document.getElementById('concurrencySlider');
915
902
  const sliderVal = document.getElementById('sliderValue');
916
903
  const simThroughput = document.getElementById('simThroughput');
917
- const simLatency = document.getElementById('simLatency');
918
904
 
919
- slider.addEventListener('input', (e) => {
920
- const val = parseInt(e.target.value, 10);
921
- sliderVal.textContent = val;
922
- const factor = val / ${config.threads || 10};
923
- simThroughput.textContent = (baseThroughput * Math.min(factor, 2.5)).toFixed(0) + '/s';
924
- simLatency.textContent = (baseLatency * Math.pow(factor, 0.8)).toFixed(1) + 'ms';
925
- });
905
+ if(slider) {
906
+ slider.addEventListener('input', (e) => {
907
+ const val = parseInt(e.target.value, 10);
908
+ sliderVal.textContent = val;
909
+ const factor = val / ${config.threads || 10};
910
+ simThroughput.textContent = (baseThroughput * Math.min(factor, 2.5)).toFixed(0) + '/s';
911
+ });
912
+ }
913
+
914
+ // Dynamic View Selection Switching Functionality
915
+ function switchPersona(persona) {
916
+ document.querySelectorAll('.persona-btn').forEach(btn => btn.classList.remove('active'));
917
+ event.target.classList.add('active');
918
+
919
+ // Hide all dynamic components initially
920
+ const layouts = ['.p-dev', '.p-devops', '.p-exec'];
921
+ layouts.forEach(selector => {
922
+ document.querySelectorAll(selector).forEach(el => el.style.display = 'none');
923
+ });
924
+
925
+ // Show specific class tags tied to selected viewport context
926
+ document.querySelectorAll('.p-' + persona).forEach(el => {
927
+ if (el.tagName === 'TR') el.style.display = 'table-row';
928
+ else if (el.classList.contains('metric-card')) el.style.display = 'block';
929
+ else el.style.display = '';
930
+ });
931
+ }
926
932
 
927
933
  new Chart(document.getElementById('volumeChart'), {
928
934
  type: 'bar',
929
935
  data: {
930
936
  labels: labels,
931
937
  datasets: [
932
- {
933
- label: 'Successful Requests',
934
- data: ${JSON.stringify(successRequestsData)},
935
- backgroundColor: '#10b981',
936
- stack: 'requests',
937
- barPercentage: 0.95,
938
- categoryPercentage: 0.95
939
- },
940
- {
941
- label: 'Failed Workloads',
942
- data: ${JSON.stringify(failedWorkloadsData)},
943
- backgroundColor: '#ef4444',
944
- stack: 'requests',
945
- barPercentage: 0.95,
946
- categoryPercentage: 0.95
947
- }
938
+ { label: 'Successful Requests', data: ${JSON.stringify(successRequestsData)}, backgroundColor: '#10b981', stack: 'requests' },
939
+ { label: 'Failed Workloads', data: ${JSON.stringify(failedWorkloadsData)}, backgroundColor: '#ef4444', stack: 'requests' }
948
940
  ]
949
941
  },
950
- options: {
951
- responsive: true,
952
- maintainAspectRatio: false,
953
- plugins: {
954
- legend: { position: 'top', labels: { color: '#94a3b8', font: { size: 11 } } }
955
- },
956
- scales: {
957
- x: { grid: { color: '#1e293b' }, ticks: { color: '#64748b' } },
958
- y: { stacked: true, grid: { color: '#1e293b' }, ticks: { color: '#64748b' } }
959
- }
960
- }
942
+ options: { responsive: true, maintainAspectRatio: false, scales: { x: { grid: { color: '#1e293b' } }, y: { stacked: true, grid: { color: '#1e293b' } } } }
961
943
  });
962
944
 
963
945
  new Chart(document.getElementById('concurrencyChart'), {
@@ -965,86 +947,31 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
965
947
  data: {
966
948
  labels: labels,
967
949
  datasets: [
968
- {
969
- label: 'Active VU Threads',
970
- data: ${JSON.stringify(activeThreadsData)},
971
- borderColor: '#38bdf8',
972
- backgroundColor: 'rgba(56, 189, 248, 0.1)',
973
- borderWidth: 2.5,
974
- pointRadius: 4,
975
- fill: true,
976
- yAxisID: 'yThreads'
977
- },
978
- {
979
- label: 'Time-to-Failure (TTF) Trend',
980
- data: ${JSON.stringify(ttfTrendData)},
981
- borderColor: '#f43f5e',
982
- borderWidth: 2,
983
- borderDash: [5, 5],
984
- pointRadius: 3,
985
- fill: false,
986
- yAxisID: 'yTtf'
987
- }
950
+ { label: 'Active VU Threads', data: ${JSON.stringify(activeThreadsData)}, borderColor: '#38bdf8', yAxisID: 'yThreads' },
951
+ { label: 'Time-to-Failure Trend', data: ${JSON.stringify(ttfTrendData)}, borderColor: '#f43f5e', yAxisID: 'yTtf' }
988
952
  ]
989
953
  },
990
- options: {
991
- responsive: true,
992
- maintainAspectRatio: false,
993
- plugins: {
994
- legend: { position: 'top', labels: { color: '#94a3b8', font: { size: 11 } } }
995
- },
996
- scales: {
997
- x: { grid: { color: '#1e293b' }, ticks: { color: '#64748b' } },
998
- y_threads: { position: 'left', grid: { color: '#1e293b' }, ticks: { color: '#38bdf8' }, title: { display: true, text: 'VUs / Threads', color: '#38bdf8' } },
999
- y_ttf: { position: 'right', grid: { drawOnChartArea: false }, ticks: { color: '#f43f5e' }, title: { display: true, text: 'TTF Index / Latency ms', color: '#f43f5e' } }
1000
- }
1001
- }
954
+ options: { responsive: true, maintainAspectRatio: false }
1002
955
  });
1003
956
 
1004
957
  new Chart(document.getElementById('statusDonutChart'), {
1005
958
  type: 'doughnut',
1006
959
  data: {
1007
- labels: ['1xx Info', '2xx Success', '3xx Redirect', '4xx Client Err', '5xx Server Err'],
1008
- datasets: [{
1009
- data: [${responseMatrix.total1xx}, ${responseMatrix.total2xx}, ${responseMatrix.total3xx}, ${responseMatrix.total4xx}, ${responseMatrix.total5xx}],
1010
- backgroundColor: ['#38bdf8', '#4ade80', '#cbd5e1', '#fde047', '#f87171'],
1011
- borderWidth: 1,
1012
- borderColor: '#1e293b'
1013
- }]
960
+ labels: ['Success', 'Client Err', 'Server Err'],
961
+ datasets: [{ data: [${responseMatrix.total2xx}, ${responseMatrix.total4xx}, ${responseMatrix.total5xx}], backgroundColor: ['#4ade80', '#fde047', '#f87171'] }]
1014
962
  },
1015
- options: {
1016
- responsive: true,
1017
- maintainAspectRatio: false,
1018
- plugins: {
1019
- legend: { position: 'top', labels: { color: '#94a3b8', font: { size: 11 } } },
1020
- cutout: '65%'
1021
- }
1022
- }
963
+ options: { responsive: true, maintainAspectRatio: false }
1023
964
  });
1024
965
 
1025
966
  new Chart(document.getElementById('ttfbScatterChart'), {
1026
967
  type: 'scatter',
1027
- data: {
1028
- datasets: [{
1029
- label: 'Request Processing Delay',
1030
- data: ${JSON.stringify(scatterPoints)},
1031
- backgroundColor: '#a855f7',
1032
- pointRadius: 4,
1033
- pointHoverRadius: 6
1034
- }]
1035
- },
1036
- options: {
1037
- responsive: true,
1038
- maintainAspectRatio: false,
1039
- plugins: {
1040
- legend: { position: 'top', labels: { color: '#94a3b8', font: { size: 11 } } }
1041
- },
1042
- scales: {
1043
- x: { grid: { color: '#1e293b' }, ticks: { color: '#64748b' }, title: { display: true, text: 'Time offset (s)', color: '#64748b' } },
1044
- y: { grid: { color: '#1e293b' }, ticks: { color: '#64748b' }, title: { display: true, text: 'TTFB / Delay (ms)', color: '#64748b' } }
1045
- }
1046
- }
968
+ data: { datasets: [{ label: 'Processing Delay', data: ${JSON.stringify(scatterPoints)}, backgroundColor: '#a855f7' }] },
969
+ options: { responsive: true, maintainAspectRatio: false }
1047
970
  });
971
+
972
+ // Initialize layout setup to display Developer view on start
973
+ document.querySelectorAll('.p-devops, .p-exec').forEach(el => el.style.display = 'none');
974
+ document.querySelectorAll('.p-dev').forEach(el => el.style.display = '');
1048
975
  </script></body></html>`;
1049
976
  try {
1050
977
  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.22",
3
+ "version": "3.1.23",
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",