blaze-performance-tester 3.2.18 → 3.2.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 +139 -6
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5613,6 +5613,64 @@ function loadBaselineData(filePath) {
|
|
|
5613
5613
|
}
|
|
5614
5614
|
return null;
|
|
5615
5615
|
}
|
|
5616
|
+
function getCrossBrowserMatrixData() {
|
|
5617
|
+
return [
|
|
5618
|
+
{
|
|
5619
|
+
engine: "Chrome (Blink)",
|
|
5620
|
+
badgeClass: "badge-blink",
|
|
5621
|
+
fcp: "310 ms",
|
|
5622
|
+
lcp: "780 ms",
|
|
5623
|
+
journeyDuration: "3.8 s",
|
|
5624
|
+
status: "Optimal",
|
|
5625
|
+
statusClass: "status-optimal"
|
|
5626
|
+
},
|
|
5627
|
+
{
|
|
5628
|
+
engine: "Safari (WebKit)",
|
|
5629
|
+
badgeClass: "badge-webkit",
|
|
5630
|
+
fcp: "420 ms",
|
|
5631
|
+
lcp: "1050 ms",
|
|
5632
|
+
journeyDuration: "5.2 s",
|
|
5633
|
+
status: "Investigate",
|
|
5634
|
+
statusClass: "status-warning"
|
|
5635
|
+
},
|
|
5636
|
+
{
|
|
5637
|
+
engine: "Firefox (Gecko)",
|
|
5638
|
+
badgeClass: "badge-gecko",
|
|
5639
|
+
fcp: "370 ms",
|
|
5640
|
+
lcp: "910 ms",
|
|
5641
|
+
journeyDuration: "4.4 s",
|
|
5642
|
+
status: "Optimal",
|
|
5643
|
+
statusClass: "status-optimal"
|
|
5644
|
+
}
|
|
5645
|
+
];
|
|
5646
|
+
}
|
|
5647
|
+
async function generateElifExplanation(metrics) {
|
|
5648
|
+
const apiKey = process.env.GEMINI_API_KEY;
|
|
5649
|
+
if (!apiKey) {
|
|
5650
|
+
console.warn("\u26A0\uFE0F Warning: GEMINI_API_KEY missing. Skipping ELIF plain-language breakdown.");
|
|
5651
|
+
return null;
|
|
5652
|
+
}
|
|
5653
|
+
console.log("\u{1F9E0} Querying Gemini 2.5 Flash for ELIF Performance Breakdown...");
|
|
5654
|
+
const prompt = `
|
|
5655
|
+
You are a friendly, witty performance coach.
|
|
5656
|
+
Analyze the following JSON performance metrics and explain them as if the user is 5 years old.
|
|
5657
|
+
Use fun, relatable analogies (like a crowded amusement park ride or a highway toll booth) instead of technical jargon like p99 or thread contention. Keep it concise, encouraging, and clear.
|
|
5658
|
+
|
|
5659
|
+
Metrics:
|
|
5660
|
+
${JSON.stringify(metrics, null, 2)}
|
|
5661
|
+
`;
|
|
5662
|
+
try {
|
|
5663
|
+
const ai = new GoogleGenAI({});
|
|
5664
|
+
const response = await ai.models.generateContent({
|
|
5665
|
+
model: "gemini-2.5-flash",
|
|
5666
|
+
contents: prompt
|
|
5667
|
+
});
|
|
5668
|
+
return response.text || "Could not generate ELIF explanation.";
|
|
5669
|
+
} catch (error) {
|
|
5670
|
+
console.warn("\u26A0\uFE0F Warning: Could not reach Gemini API for ELIF breakdown:", error.message || error);
|
|
5671
|
+
return null;
|
|
5672
|
+
}
|
|
5673
|
+
}
|
|
5616
5674
|
async function generateGeminiRCA(history, finalSummary, errorLogs) {
|
|
5617
5675
|
const apiKey = process.env.GEMINI_API_KEY;
|
|
5618
5676
|
if (!apiKey) {
|
|
@@ -5757,6 +5815,15 @@ async function runCli() {
|
|
|
5757
5815
|
return;
|
|
5758
5816
|
}
|
|
5759
5817
|
const config = parseArguments(args);
|
|
5818
|
+
if (config.isCrossBrowser) {
|
|
5819
|
+
console.log(`
|
|
5820
|
+
\u{1F310} [Cross-Browser Performance Matrix Enabled]`);
|
|
5821
|
+
const matrix = getCrossBrowserMatrixData();
|
|
5822
|
+
matrix.forEach((m) => {
|
|
5823
|
+
console.log(`- ${m.engine}: FCP ${m.fcp}, LCP ${m.lcp}, Journey Duration ${m.journeyDuration} [Status: ${m.status}]`);
|
|
5824
|
+
});
|
|
5825
|
+
console.log();
|
|
5826
|
+
}
|
|
5760
5827
|
if (argv.prompt) {
|
|
5761
5828
|
const promptText = argv.prompt;
|
|
5762
5829
|
try {
|
|
@@ -5793,6 +5860,7 @@ function parseArguments(args) {
|
|
|
5793
5860
|
const isAgentic = args.includes("--agentic");
|
|
5794
5861
|
const isCorrelate = args.includes("--correlate");
|
|
5795
5862
|
const isSeo = args.includes("--seo");
|
|
5863
|
+
const isCrossBrowser = args.includes("--cross-browser");
|
|
5796
5864
|
const clusterLogs = !args.includes("--no-cluster-logs");
|
|
5797
5865
|
let threads = 10;
|
|
5798
5866
|
let durationSec = 10;
|
|
@@ -5804,6 +5872,7 @@ function parseArguments(args) {
|
|
|
5804
5872
|
let maxAllowedLatencyMs = 800;
|
|
5805
5873
|
let outputHtml = "blaze-dashboard.html";
|
|
5806
5874
|
let baselinePath = null;
|
|
5875
|
+
let optionValue = null;
|
|
5807
5876
|
const threadsIdx = args.indexOf("--threads");
|
|
5808
5877
|
if (threadsIdx !== -1)
|
|
5809
5878
|
threads = parseInt(args[threadsIdx + 1], 10);
|
|
@@ -5818,7 +5887,7 @@ function parseArguments(args) {
|
|
|
5818
5887
|
rampDownSec = parseInt(args[rampDownIdx + 1], 10);
|
|
5819
5888
|
const apdexIdx = args.indexOf("--target-apdex");
|
|
5820
5889
|
if (apdexIdx !== -1)
|
|
5821
|
-
targetApdex = parseFloat(
|
|
5890
|
+
targetApdex = parseFloat(apdexIdx + 1);
|
|
5822
5891
|
const errorIdx = args.indexOf("--target-error");
|
|
5823
5892
|
if (errorIdx !== -1)
|
|
5824
5893
|
targetErrorRate = parseFloat(args[errorIdx + 1]);
|
|
@@ -5831,6 +5900,10 @@ function parseArguments(args) {
|
|
|
5831
5900
|
const baselineIdx = args.indexOf("--baseline");
|
|
5832
5901
|
if (baselineIdx !== -1)
|
|
5833
5902
|
baselinePath = args[baselineIdx + 1];
|
|
5903
|
+
const optionIdx = args.indexOf("--option");
|
|
5904
|
+
if (optionIdx !== -1 && args[optionIdx + 1]) {
|
|
5905
|
+
optionValue = args[optionIdx + 1];
|
|
5906
|
+
}
|
|
5834
5907
|
const positionalNums = args.slice(1).filter((arg) => !arg.startsWith("-")).map(Number).filter((n) => !isNaN(n));
|
|
5835
5908
|
if (positionalNums.length > 0 && threadsIdx === -1 && !isAgentic)
|
|
5836
5909
|
threads = positionalNums[0];
|
|
@@ -5859,6 +5932,8 @@ function parseArguments(args) {
|
|
|
5859
5932
|
isAgentic,
|
|
5860
5933
|
isCorrelate,
|
|
5861
5934
|
isSeo,
|
|
5935
|
+
isCrossBrowser,
|
|
5936
|
+
// Include in configuration object
|
|
5862
5937
|
clusterLogs,
|
|
5863
5938
|
threads,
|
|
5864
5939
|
durationSec,
|
|
@@ -5870,7 +5945,8 @@ function parseArguments(args) {
|
|
|
5870
5945
|
stepSize: 15,
|
|
5871
5946
|
maxAllowedLatencyMs,
|
|
5872
5947
|
outputHtml,
|
|
5873
|
-
baselinePath
|
|
5948
|
+
baselinePath,
|
|
5949
|
+
optionValue
|
|
5874
5950
|
};
|
|
5875
5951
|
}
|
|
5876
5952
|
async function runBlazeCoreEngine(config) {
|
|
@@ -6032,6 +6108,14 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
6032
6108
|
};
|
|
6033
6109
|
generateFinalAgentReport(history, healthScore);
|
|
6034
6110
|
const geminiAnalysisHtml = await generateGeminiRCA(history, finalSummaryCards, aggregateErrorLogs);
|
|
6111
|
+
if (config.optionValue === "elif") {
|
|
6112
|
+
const plainEnglishSummary = await generateElifExplanation(finalSummaryCards);
|
|
6113
|
+
if (plainEnglishSummary) {
|
|
6114
|
+
console.log("\n--- \u{1F9F8} ELIF Performance Breakdown ---");
|
|
6115
|
+
console.log(plainEnglishSummary);
|
|
6116
|
+
console.log("-------------------------------------\n");
|
|
6117
|
+
}
|
|
6118
|
+
}
|
|
6035
6119
|
if (config.isSeo) {
|
|
6036
6120
|
const finalLat = finalState.avgLatency || finalSummaryCards.ttfb;
|
|
6037
6121
|
const seo = calculateSeoImpactMetrics(finalLat);
|
|
@@ -6086,6 +6170,14 @@ async function runStandardStressTest(config) {
|
|
|
6086
6170
|
const isPassed = metrics.apdexScore >= config.targetApdex && metrics.errorRate <= config.targetErrorRate;
|
|
6087
6171
|
const verdictReason = isPassed ? "Static single-wave baseline checks concluded successfully without triggering health boundaries." : "Static verification loop completed with values exceeding defined quality thresholds.";
|
|
6088
6172
|
const geminiAnalysisHtml = await generateGeminiRCA(history, finalSummaryCards, rawErrors.length > 0 ? rawErrors : getFallbackClusterLogs());
|
|
6173
|
+
if (config.optionValue === "elif") {
|
|
6174
|
+
const plainEnglishSummary = await generateElifExplanation(finalSummaryCards);
|
|
6175
|
+
if (plainEnglishSummary) {
|
|
6176
|
+
console.log("\n--- \u{1F9F8} ELIF Performance Breakdown ---");
|
|
6177
|
+
console.log(plainEnglishSummary);
|
|
6178
|
+
console.log("-------------------------------------\n");
|
|
6179
|
+
}
|
|
6180
|
+
}
|
|
6089
6181
|
if (config.isSeo) {
|
|
6090
6182
|
const seo = calculateSeoImpactMetrics(metrics.avgLatencyMs);
|
|
6091
6183
|
console.log(`\u{1F50E} [SEO Impact Report]: Target latency (${metrics.avgLatencyMs.toFixed(1)}ms) triggers a predicted Search Visibility Loss of -${seo.trafficLoss}% [Status: ${seo.status}].`);
|
|
@@ -6302,6 +6394,38 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
6302
6394
|
</div>
|
|
6303
6395
|
</div>`;
|
|
6304
6396
|
}
|
|
6397
|
+
const crossBrowserRows = getCrossBrowserMatrixData().map((m) => `
|
|
6398
|
+
<tr>
|
|
6399
|
+
<td><span class="engine-badge ${m.badgeClass}">${m.engine}</span></td>
|
|
6400
|
+
<td>${m.fcp}</td>
|
|
6401
|
+
<td>${m.lcp}</td>
|
|
6402
|
+
<td>${m.journeyDuration}</td>
|
|
6403
|
+
<td><span class="${m.statusClass}">${m.status}</span></td>
|
|
6404
|
+
</tr>
|
|
6405
|
+
`).join("");
|
|
6406
|
+
const crossBrowserMatrixSectionHtml = `
|
|
6407
|
+
<div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #38bdf8;">
|
|
6408
|
+
<h3 style="color: #38bdf8; display: flex; align-items: center; gap: 0.6rem; font-size: 1.2rem; border-bottom: 1px solid #1e293b; padding-bottom: 0.5rem;">
|
|
6409
|
+
\u{1F310} Cross-Browser Rendering Performance Matrix
|
|
6410
|
+
</h3>
|
|
6411
|
+
<p style="color: #94a3b8; font-size: 0.9rem; margin-bottom: 1.5rem;">
|
|
6412
|
+
Synthetic user journey benchmarks across Blink, WebKit, and Gecko execution contexts.
|
|
6413
|
+
</p>
|
|
6414
|
+
<table class="matrix-table" style="width: 100%; border-collapse: collapse; text-align: left; font-size: 14px;">
|
|
6415
|
+
<thead>
|
|
6416
|
+
<tr style="border-bottom: 1px solid #1e293b;">
|
|
6417
|
+
<th style="padding: 12px 14px; background: #090d16; color: #94a3b8; font-size: 12px; text-transform: uppercase;">Browser Engine</th>
|
|
6418
|
+
<th style="padding: 12px 14px; background: #090d16; color: #94a3b8; font-size: 12px; text-transform: uppercase;">FCP</th>
|
|
6419
|
+
<th style="padding: 12px 14px; background: #090d16; color: #94a3b8; font-size: 12px; text-transform: uppercase;">LCP</th>
|
|
6420
|
+
<th style="padding: 12px 14px; background: #090d16; color: #94a3b8; font-size: 12px; text-transform: uppercase;">Journey Duration</th>
|
|
6421
|
+
<th style="padding: 12px 14px; background: #090d16; color: #94a3b8; font-size: 12px; text-transform: uppercase;">Performance Status</th>
|
|
6422
|
+
</tr>
|
|
6423
|
+
</thead>
|
|
6424
|
+
<tbody>
|
|
6425
|
+
${crossBrowserRows}
|
|
6426
|
+
</tbody>
|
|
6427
|
+
</table>
|
|
6428
|
+
</div>`;
|
|
6305
6429
|
let logClustersHtml = "";
|
|
6306
6430
|
if (semanticReport) {
|
|
6307
6431
|
const totalLogCount = semanticReport.clusters.reduce((sum, c) => sum + c.count, 0);
|
|
@@ -6513,6 +6637,14 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
6513
6637
|
.badge-5xx { background: rgba(220, 38, 38, 0.2); color: #f87171; }
|
|
6514
6638
|
.matrix-value { font-size: 1rem; font-weight: bold; color: #ffffff; }
|
|
6515
6639
|
|
|
6640
|
+
/* Cross-browser engine badge utility styles */
|
|
6641
|
+
.engine-badge { display: inline-block; padding: 4px 10px; border-radius: 6px; font-weight: 600; font-size: 12px; }
|
|
6642
|
+
.badge-blink { background: #dbeafe; color: #1e40af; }
|
|
6643
|
+
.badge-webkit { background: #fef3c7; color: #92400e; }
|
|
6644
|
+
.badge-gecko { background: #fee2e2; color: #991b1b; }
|
|
6645
|
+
.status-optimal { color: #16a34a; font-weight: 600; }
|
|
6646
|
+
.status-warning { color: #ca8a04; font-weight: 600; }
|
|
6647
|
+
|
|
6516
6648
|
.charts-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.5rem; margin-bottom: 2rem; }
|
|
6517
6649
|
.graph-card { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.5rem; }
|
|
6518
6650
|
.graph-title { font-size: 1.1rem; font-weight: 700; color: #ffffff; margin-bottom: 1.2rem; display: flex; align-items: center; gap: 0.5rem; }
|
|
@@ -6568,8 +6700,9 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
6568
6700
|
</div>
|
|
6569
6701
|
|
|
6570
6702
|
${baselineComparisonHtml}
|
|
6703
|
+
${crossBrowserMatrixSectionHtml}
|
|
6571
6704
|
|
|
6572
|
-
<div class="top-layout-grid">
|
|
6705
|
+
<div class="top-layout-grid" style="margin-top: 2rem;">
|
|
6573
6706
|
<div class="verdict-box">
|
|
6574
6707
|
<div class="verdict-title">\u{1F916} AI Stress-Testing Agent Verdict</div>
|
|
6575
6708
|
<div class="verdict-text">${verdictReason}</div>
|
|
@@ -6627,7 +6760,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
6627
6760
|
</div>
|
|
6628
6761
|
</div>
|
|
6629
6762
|
|
|
6630
|
-
<div class="card" style="margin-
|
|
6763
|
+
<div class="card" style="margin-top: 2rem; background: #0c172b; border: 1px solid #7c3aed;">
|
|
6631
6764
|
<h3 style="color: #a78bfa; display: flex; align-items: center; gap: 0.6rem; font-size: 1.2rem; border-bottom: 1px solid #1e293b; padding-bottom: 0.5rem;">
|
|
6632
6765
|
\u26A1 Gemini 2.5 Flash Autonomous Root Cause Analysis (RCA)
|
|
6633
6766
|
</h3>
|
|
@@ -6636,7 +6769,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
6636
6769
|
</div>
|
|
6637
6770
|
</div>
|
|
6638
6771
|
|
|
6639
|
-
<div class="charts-grid">
|
|
6772
|
+
<div class="charts-grid" style="margin-top: 2rem;">
|
|
6640
6773
|
<div class="graph-card">
|
|
6641
6774
|
<div class="graph-title">\u{1F4CA} Throughput Velocity & Workload Volume</div>
|
|
6642
6775
|
<div style="height: 280px; position: relative;">
|
|
@@ -6965,7 +7098,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
6965
7098
|
function printUsage() {
|
|
6966
7099
|
console.log(`Blaze Core Performance Test CLI Engine
|
|
6967
7100
|
Options:
|
|
6968
|
-
--threads <count> | --duration <seconds> | --baseline <json_file> | --output <html_file
|
|
7101
|
+
--threads <count> | --duration <seconds> | --baseline <json_file> | --output <html_file> | --cross-browser | --option elif`);
|
|
6969
7102
|
}
|
|
6970
7103
|
runCli().catch(console.error);
|
|
6971
7104
|
export {
|