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 +83 -156
- 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: 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
|
|
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
|
-
<
|
|
748
|
-
|
|
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">±${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
|
-
|
|
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"
|
|
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
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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: ['
|
|
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
|
-
|
|
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
|