blaze-performance-tester 3.1.26 → 3.1.27

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: 0, 502: 0, 503: 0, 504: 0 };
470
+ const codeCounts = { 400: 0, 401: 0, 403: 0, 404: 0, 429: 0, 500: 502, 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,26 +540,6 @@ 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>`;
563
543
  const firstTimestamp = rawRequests[0]?.timestampMs || Date.now();
564
544
  const scatterPoints = rawRequests.slice(0, 180).map((r) => ({
565
545
  x: Number(((r.timestampMs - firstTimestamp) / 1e3).toFixed(2)),
@@ -584,7 +564,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
584
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>
585
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>
586
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>
587
- <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>
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>
588
568
  </tr>
589
569
  </thead>
590
570
  <tbody>
@@ -592,6 +572,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
592
572
  let catColor = "#fb923c";
593
573
  if (c.category === "Authentication_Error") catColor = "#c084fc";
594
574
  if (c.category === "Product_Error") catColor = "#f87171";
575
+ if (c.category === "Environment_Infrastructure_Error") catColor = "#fb923c";
595
576
  let sevBg = c.severity === "CRITICAL" ? "#dc2626" : "#ea580c";
596
577
  const rawTemplate = c.template || "";
597
578
  const cleanedTemplate = rawTemplate.replace(/\[\d{4}-\d{2}-\d{2}.*?\]\s*/, "");
@@ -606,6 +587,9 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
606
587
  <div style="background: #090d16; border-radius: 4px; padding: 0.6rem 0.8rem; border-left: 3px solid #1e293b; margin-bottom: 0.5rem;">
607
588
  <code style="color: #cbd5e1; font-family: monospace; font-size: 0.9rem; white-space: pre-wrap; word-break: break-all;">${cleanedTemplate}</code>
608
589
  </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>
609
593
  </td>
610
594
  </tr>`;
611
595
  }).join("")}
@@ -622,16 +606,21 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
622
606
  <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;">
623
607
  \u{1F50E} SEO Rank Impact & Visibility Loss Predictor
624
608
  </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>
625
612
  <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;">
626
613
  <div style="background: #090d16; padding: 1.25rem; border-radius: 6px; border: 1px solid #1e293b; text-align: center;">
627
614
  <div class="card-title" style="color: #94a3b8;">Est. Organic Traffic Loss</div>
628
615
  <div style="font-size: 2rem; font-weight: bold; color: ${seoMetrics.color};">
629
616
  ${seoMetrics.trafficLoss > 0 ? "-" : ""}${seoMetrics.trafficLoss}%
630
617
  </div>
618
+ <div style="font-size: 0.8rem; color: #64748b; margin-top: 0.25rem;">compared to 200ms sweet-spot</div>
631
619
  </div>
632
620
  <div style="background: #090d16; padding: 1.25rem; border-radius: 6px; border: 1px solid #1e293b;">
633
621
  <div class="card-title">Search Visibility Status</div>
634
622
  <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>
635
624
  </div>
636
625
  <div style="background: #090d16; padding: 1.25rem; border-radius: 6px; border: 1px solid #1e293b;">
637
626
  <div class="card-title">Googlebot Crawl Budget Impact</div>
@@ -657,6 +646,30 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
657
646
  <div style="font-size: 0.7rem; color: #64748b; text-transform: uppercase;">Sim. Throughput</div>
658
647
  <div id="simThroughput" style="font-size: 1.2rem; font-weight: bold; color: #f97316;">${cards.throughput.toFixed(0)}/s</div>
659
648
  </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
+ </div>
654
+ </div>
655
+ </div>`;
656
+ const rightSizingHtml = `
657
+ <div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
658
+ <h3 style="color: #38bdf8; display: flex; align-items: center; gap: 0.5rem; font-size: 1.2rem;">
659
+ \u2601\uFE0F Infrastructure Right-Sizing & Cloud Cost Projections
660
+ </h3>
661
+ <div style="grid-template-columns: repeat(3, 1fr); display: grid; gap: 1rem; margin-top: 1rem;">
662
+ <div style="background: #090d16; padding: 1rem; border-radius: 6px; border: 1px solid #1e293b;">
663
+ <div class="card-title">Est. Monthly Cloud Cost</div>
664
+ <div class="card-value green">$${estimatedMonthlyCost} <span class="unit">/mo</span></div>
665
+ </div>
666
+ <div style="background: #090d16; padding: 1rem; border-radius: 6px; border: 1px solid #1e293b;">
667
+ <div class="card-title">Recommended CPU Right-Sizing</div>
668
+ <div class="card-value purple">${recommendedCpuCores} <span class="unit">vCores</span></div>
669
+ </div>
670
+ <div style="background: #090d16; padding: 1rem; border-radius: 6px; border: 1px solid #1e293b;">
671
+ <div class="card-title">Recommended Memory Allocation</div>
672
+ <div class="card-value orange">${recommendedRamGb} <span class="unit">GB RAM</span></div>
660
673
  </div>
661
674
  </div>
662
675
  </div>`;
@@ -679,7 +692,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
679
692
  <style>
680
693
  body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0b111e; color: #f8fafc; margin: 0; padding: 2rem; }
681
694
  .container { max-width: 1300px; margin: 0 auto; }
682
- .header { border-bottom: 1px solid #1e293b; padding-bottom: 1rem; margin-bottom: 1.5rem; display: flex; justify-content: space-between; align-items: center; }
695
+ .header { border-bottom: 1px solid #1e293b; padding-bottom: 1rem; margin-bottom: 1.5rem; }
683
696
  h1 { color: #38bdf8; margin: 0; font-size: 2rem; }
684
697
  .meta { color: #94a3b8; font-size: 0.9rem; margin-top: 0.5rem; }
685
698
 
@@ -703,7 +716,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
703
716
  .gauge-container-box { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.25rem; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; }
704
717
  .gauge-title { font-size: 0.85rem; font-weight: bold; color: #94a3b8; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 1rem; }
705
718
 
706
- .matrix-box { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.25rem; display: flex; flex-direction: column; justify-content: space-between; }
719
+ .matrix-box { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.25rem; }
707
720
  .matrix-title { font-size: 1.1rem; font-weight: bold; color: #ffffff; margin-bottom: 1rem; }
708
721
  .matrix-box .matrix-row { display: flex; justify-content: space-between; align-items: center; padding: 0.6rem 0; border-bottom: 1px solid #1e293b; }
709
722
  .matrix-box .matrix-row:last-child { border-bottom: none; }
@@ -731,10 +744,8 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
731
744
  </style></head><body>
732
745
  <div class="container">
733
746
  <div class="header">
734
- <div>
735
- <h1>\u{1F525} Blaze Core Performance Analysis</h1>
736
- <div class="meta">Target Script: <code>${config.targetScript}</code></div>
737
- </div>
747
+ <h1>\u{1F525} Blaze Core Performance Analysis</h1>
748
+ <div class="meta">Target Script: <code>${config.targetScript}</code></div>
738
749
  </div>
739
750
 
740
751
  <div class="cards-wrapper">
@@ -779,6 +790,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
779
790
  <div class="verdict-waves">${waveListItems}</div>
780
791
  </div>
781
792
 
793
+ <!-- IMPLEMENTED CARD FEATURE 76: Executive Health Gauges Panel -->
782
794
  <div class="gauge-container-box">
783
795
  <div class="gauge-title">Blaze Run Health Score</div>
784
796
  <div style="position: relative; width: 140px; height: 140px; display: flex; align-items: center; justify-content: center;">
@@ -786,39 +798,46 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
786
798
  <circle cx="70" cy="70" r="58" stroke="#1e293b" stroke-width="12" fill="transparent"/>
787
799
  <circle cx="70" cy="70" r="58" stroke="${gaugeColor}" stroke-width="12" fill="transparent"
788
800
  stroke-dasharray="364.4" stroke-dashoffset="${364.4 - 364.4 * cards.healthScore / 100}"
789
- stroke-linecap="round"/>
801
+ stroke-linecap="round" style="transition: stroke-dashoffset 1s ease-out;"/>
790
802
  </svg>
791
803
  <div style="position: absolute; text-align: center;">
792
804
  <div style="font-size: 2.2rem; font-weight: 800; color: #ffffff; line-height: 1;">${cards.healthScore}</div>
793
805
  <div style="font-size: 0.75rem; color: #64748b; font-weight: bold; margin-top: 0.2rem; text-transform: uppercase;">/ 100</div>
794
806
  </div>
795
807
  </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>
796
811
  </div>
797
812
 
798
813
  <div class="matrix-box">
799
- <div>
800
- <div class="matrix-title">\u{1F4CB} HTTP Response Matrix</div>
801
- <div class="matrix-row">
802
- <div class="matrix-label">Successful <span class="matrix-badge badge-2xx">2xx</span></div>
803
- <div class="matrix-value">${responseMatrix.total2xx}</div>
804
- </div>
805
- <div class="matrix-row">
806
- <div class="matrix-label">Client Error <span class="matrix-badge badge-4xx">4xx</span></div>
807
- <div class="matrix-value">${responseMatrix.total4xx}</div>
808
- </div>
809
- <div class="matrix-row">
810
- <div class="matrix-label">Server Error <span class="matrix-badge badge-5xx">5xx</span></div>
811
- <div class="matrix-value">${responseMatrix.total5xx}</div>
812
- </div>
814
+ <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
+ <div class="matrix-row">
820
+ <div class="matrix-label">Successful <span class="matrix-badge badge-2xx">2xx</span></div>
821
+ <div class="matrix-value">${responseMatrix.total2xx}</div>
822
+ </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
+ <div class="matrix-row">
828
+ <div class="matrix-label">Client Error <span class="matrix-badge badge-4xx">4xx</span></div>
829
+ <div class="matrix-value">${responseMatrix.total4xx}</div>
830
+ </div>
831
+ <div class="matrix-row">
832
+ <div class="matrix-label">Server Error <span class="matrix-badge badge-5xx">5xx</span></div>
833
+ <div class="matrix-value">${responseMatrix.total5xx}</div>
813
834
  </div>
814
835
 
815
- <div>
816
- <div class="matrix-title" style="margin-top: 1.5rem; font-size: 0.85rem; border-top: 1px solid #1e293b; padding-top: 1rem; color: #94a3b8; text-transform: uppercase; letter-spacing: 0.05em;">
817
- \u{1F522} HTTP Status Code Breakdown Rate
818
- </div>
819
- <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; margin-top: 0.5rem;">
820
- ${breakdownGridHtml}
821
- </div>
836
+ <div class="matrix-title" style="margin-top: 1.5rem; font-size: 0.85rem; border-top: 1px solid #1e293b; padding-top: 1rem; color: #94a3b8; text-transform: uppercase; letter-spacing: 0.05em;">
837
+ \u{1F522} HTTP Status Code Breakdown Rate
838
+ </div>
839
+ <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; margin-top: 0.5rem;">
840
+ ${breakdownGridHtml}
822
841
  </div>
823
842
  </div>
824
843
  </div>
@@ -862,6 +881,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
862
881
  <th>Throughput</th>
863
882
  <th>Avg Latency</th>
864
883
  <th>P95 Latency</th>
884
+ <th>Error Rate</th>
865
885
  <th>Status</th>
866
886
  </tr>
867
887
  </thead>
@@ -873,6 +893,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
873
893
  <td>${h.throughput.toFixed(0)} req/sec</td>
874
894
  <td>${h.avgLatency.toFixed(1)} ms</td>
875
895
  <td>${h.p95Latency.toFixed(1)} ms</td>
896
+ <td>${(h.errorRate * 100).toFixed(2)}%</td>
876
897
  <td><span class="badge ${isPassed ? "badge-success" : "badge-fail"}">${isPassed ? "SLO PASS" : "SLO BREACH"}</span></td>
877
898
  </tr>`;
878
899
  }).join("")}
@@ -888,30 +909,55 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
888
909
  <script>
889
910
  const labels = ${JSON.stringify(labels)};
890
911
  const baseThroughput = ${cards.throughput};
912
+ const baseLatency = ${cards.ttfb};
891
913
 
892
914
  const slider = document.getElementById('concurrencySlider');
893
915
  const sliderVal = document.getElementById('sliderValue');
894
916
  const simThroughput = document.getElementById('simThroughput');
917
+ const simLatency = document.getElementById('simLatency');
895
918
 
896
- if(slider) {
897
- slider.addEventListener('input', (e) => {
898
- const val = parseInt(e.target.value, 10);
899
- sliderVal.textContent = val;
900
- const factor = val / ${config.threads || 10};
901
- simThroughput.textContent = (baseThroughput * Math.min(factor, 2.5)).toFixed(0) + '/s';
902
- });
903
- }
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
+ });
904
926
 
905
927
  new Chart(document.getElementById('volumeChart'), {
906
928
  type: 'bar',
907
929
  data: {
908
930
  labels: labels,
909
931
  datasets: [
910
- { label: 'Successful Requests', data: ${JSON.stringify(successRequestsData)}, backgroundColor: '#10b981', stack: 'requests' },
911
- { label: 'Failed Workloads', data: ${JSON.stringify(failedWorkloadsData)}, backgroundColor: '#ef4444', stack: 'requests' }
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
+ }
912
948
  ]
913
949
  },
914
- options: { responsive: true, maintainAspectRatio: false, scales: { x: { grid: { color: '#1e293b' } }, y: { stacked: true, grid: { color: '#1e293b' } } } }
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
+ }
915
961
  });
916
962
 
917
963
  new Chart(document.getElementById('concurrencyChart'), {
@@ -919,26 +965,85 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
919
965
  data: {
920
966
  labels: labels,
921
967
  datasets: [
922
- { label: 'Active VU Threads', data: ${JSON.stringify(activeThreadsData)}, borderColor: '#38bdf8', yAxisID: 'yThreads' },
923
- { label: 'Time-to-Failure Trend', data: ${JSON.stringify(ttfTrendData)}, borderColor: '#f43f5e', yAxisID: 'yTtf' }
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
+ }
924
988
  ]
925
989
  },
926
- options: { responsive: true, maintainAspectRatio: false }
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
+ }
927
1002
  });
928
1003
 
929
1004
  new Chart(document.getElementById('statusDonutChart'), {
930
1005
  type: 'doughnut',
931
1006
  data: {
932
- labels: ['Success', 'Client Err', 'Server Err'],
933
- datasets: [{ data: [${responseMatrix.total2xx}, ${responseMatrix.total4xx}, ${responseMatrix.total5xx}], backgroundColor: ['#4ade80', '#fde047', '#f87171'] }]
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
+ }]
934
1014
  },
935
- options: { responsive: true, maintainAspectRatio: false }
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
+ }
936
1023
  });
937
1024
 
938
1025
  new Chart(document.getElementById('ttfbScatterChart'), {
939
1026
  type: 'scatter',
940
- data: { datasets: [{ label: 'Processing Delay', data: ${JSON.stringify(scatterPoints)}, backgroundColor: '#a855f7' }] },
941
- options: { responsive: true, maintainAspectRatio: false }
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
+ }
942
1047
  });
943
1048
  </script></body></html>`;
944
1049
  try {
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blaze-performance-tester",
3
- "version": "3.1.26",
3
+ "version": "3.1.27",
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",