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 +174 -69
- package/dist/index.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
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:
|
|
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;
|
|
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;
|
|
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
|
-
<
|
|
735
|
-
|
|
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
|
-
|
|
801
|
-
<div class="matrix-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
<div class="matrix-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
<div class="matrix-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
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
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
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
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
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
|
-
{
|
|
911
|
-
|
|
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: {
|
|
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
|
-
{
|
|
923
|
-
|
|
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: {
|
|
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: [{
|
|
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: {
|
|
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: {
|
|
941
|
-
|
|
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
|