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.
Files changed (2) hide show
  1. package/dist/cli.js +139 -6
  2. 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(args[apdexIdx + 1]);
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-bottom: 2rem; background: #0c172b; border: 1px solid #7c3aed;">
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 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blaze-performance-tester",
3
- "version": "3.2.18",
3
+ "version": "3.2.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",