blaze-performance-tester 3.1.31 → 3.1.33

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
@@ -87,87 +87,6 @@ var mathUtils = {
87
87
  return sorted[Math.max(0, index)];
88
88
  }
89
89
  };
90
- async function fetchRcaInsights(semanticReport, apiKey) {
91
- if (!semanticReport || !semanticReport.clusters || semanticReport.clusters.length === 0) {
92
- return `<ul><li><strong>Nominal Operational Bounds:</strong> No cluster-level anomalies or processing faults were registered during this execution frame.</li></ul>`;
93
- }
94
- const errorSummary = semanticReport.clusters.map((c) => `[Count: ${c.count}] Category: ${c.category} -> Pattern: ${c.template}`).join("\n");
95
- try {
96
- const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=${apiKey}`, {
97
- method: "POST",
98
- headers: {
99
- "Content-Type": "application/json"
100
- },
101
- body: JSON.stringify({
102
- systemInstruction: {
103
- parts: [
104
- {
105
- text: "You are a principal systems architect and site reliability engineer. Return clean, direct HTML list items (using <li> tags, no raw markdown blocks) summarizing diagnostics."
106
- }
107
- ]
108
- },
109
- contents: [
110
- {
111
- role: "user",
112
- parts: [
113
- {
114
- text: `Analyze these performance test errors and provide 3 bullet points detailing the likely backend bottleneck (e.g., database connection pool exhaustion) and practical configuration fixes.
115
-
116
- Error Log Patterns:
117
- ${errorSummary}`
118
- }
119
- ]
120
- }
121
- ],
122
- generationConfig: {
123
- temperature: 0.2
124
- }
125
- })
126
- });
127
- if (!response.ok) {
128
- return `<span style="color: #ef4444;">AI Completion API Error: ${response.status} ${response.statusText}</span>`;
129
- }
130
- const data = await response.json();
131
- return data.candidates?.[0]?.content?.parts?.[0]?.text || "<li>Failed to aggregate autonomous analysis parameters.</li>";
132
- } catch (error) {
133
- return `<span style="color: #ef4444;">Failed to resolve external cloud model: ${error.message}</span>`;
134
- }
135
- }
136
- async function fetchIncidentNarrative(history, semanticReport, apiKey) {
137
- const timelineSummary = history.map((h) => `Wave Tier [${h.threads} VUs] -> Throughput: ${h.throughput.toFixed(0)} req/s, Avg Latency: ${h.avgLatency.toFixed(1)}ms, Error Rate: ${(h.errorRate * 100).toFixed(2)}%`).join("\n");
138
- const logSummary = semanticReport && semanticReport.clusters ? semanticReport.clusters.map((c) => `[Error Count: ${c.count}] Pattern Blueprint: ${c.template}`).join("\n") : "No major software errors logged.";
139
- try {
140
- const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=${apiKey}`, {
141
- method: "POST",
142
- headers: { "Content-Type": "application/json" },
143
- body: JSON.stringify({
144
- systemInstruction: {
145
- parts: [{
146
- text: "You are an expert technical writer and lead SRE. Write a fluid, highly professional, plain-English narrative story explaining the timeline of how the system degraded during this load test. Synthesize the raw timeline curves and matching log errors together. Return clean, elegant paragraphs (<p> text </p>) using standard HTML inline formatting elements like <strong> where needed. Do not wrap the response in markdown block quotes (like ```html)."
147
- }]
148
- },
149
- contents: [{
150
- role: "user",
151
- parts: [{
152
- text: `Analyze this historical load pipeline timeline and corresponding logs. Write a clear narrative detailing the failure journey as concurrency grew:
153
-
154
- === Chronological Testing Waves ===
155
- ${timelineSummary}
156
-
157
- === Captured Structural Error Blueprints ===
158
- ${logSummary}`
159
- }]
160
- }],
161
- generationConfig: { temperature: 0.4 }
162
- })
163
- });
164
- if (!response.ok) return `<em>Narrative generator unavailable: ${response.statusText}</em>`;
165
- const data = await response.json();
166
- return data.candidates?.[0]?.content?.parts?.[0]?.text || "<em>Failed to construct incident storyline parameters.</em>";
167
- } catch (e) {
168
- return `<em>Failed to compile conversational telemetry narrative: ${e.message}</em>`;
169
- }
170
- }
171
90
  async function executeTestPipeline(config) {
172
91
  if (!blazeCore || typeof blazeCore.runCorrelatedTransaction !== "function") {
173
92
  console.error("\u274C Error: runCorrelatedTransaction function is missing from the compiled binary bindings.");
@@ -176,13 +95,13 @@ async function executeTestPipeline(config) {
176
95
  const transactionalScenario = [
177
96
  {
178
97
  name: "Fetch Target Anti-Forgery Nonce",
179
- url: "[https://httpbin.org/json](https://httpbin.org/json)",
98
+ url: "https://httpbin.org/json",
180
99
  method: "GET",
181
100
  body: null
182
101
  },
183
102
  {
184
103
  name: "Perform Contextual Post Action",
185
- url: "[https://httpbin.org/post?verification=](https://httpbin.org/post?verification=)${csrf_token}",
104
+ url: "https://httpbin.org/post?verification=${csrf_token}",
186
105
  method: "POST",
187
106
  body: JSON.stringify({
188
107
  data: "performance_payload",
@@ -229,7 +148,6 @@ function parseArguments(args) {
229
148
  let maxThreads = 300;
230
149
  let maxAllowedLatencyMs = 800;
231
150
  let outputHtml = "blaze-dashboard.html";
232
- let aiKey = process.env.GEMINI_API_KEY || "";
233
151
  const threadsIdx = args.indexOf("--threads");
234
152
  if (threadsIdx !== -1) threads = parseInt(args[threadsIdx + 1], 10);
235
153
  const durationIdx = args.indexOf("--duration");
@@ -242,8 +160,6 @@ function parseArguments(args) {
242
160
  if (maxThreadsIdx !== -1) maxThreads = parseInt(args[maxThreadsIdx + 1], 10);
243
161
  const outputIdx = args.indexOf("--output");
244
162
  if (outputIdx !== -1) outputHtml = args[outputIdx + 1];
245
- const aiKeyIdx = args.indexOf("--ai-key");
246
- if (aiKeyIdx !== -1) aiKey = args[aiKeyIdx + 1];
247
163
  const positionalNums = args.slice(1).filter((arg) => !arg.startsWith("-")).map(Number).filter((n) => !isNaN(n));
248
164
  if (positionalNums.length > 0 && threadsIdx === -1 && !isAgentic) threads = positionalNums[0];
249
165
  if (positionalNums.length > 1 && durationIdx === -1 && !isAgentic) durationSec = positionalNums[1];
@@ -275,8 +191,7 @@ function parseArguments(args) {
275
191
  maxThreads,
276
192
  stepSize: 15,
277
193
  maxAllowedLatencyMs,
278
- outputHtml,
279
- aiKey
194
+ outputHtml
280
195
  };
281
196
  }
282
197
  async function runBlazeCoreEngine(config) {
@@ -412,20 +327,12 @@ async function runIntelligentAgenticStressTest(config) {
412
327
  currentThreads += nextStep;
413
328
  }
414
329
  let semanticReport = null;
415
- let rcaInsights = "";
416
- let incidentNarrative = "";
417
330
  if (config.clusterLogs) {
418
331
  if (aggregateErrorLogs.length === 0) {
419
332
  aggregateErrorLogs = getFallbackClusterLogs();
420
333
  }
421
334
  const analyzer = new LogAnalyzer();
422
335
  semanticReport = analyzer.process(aggregateErrorLogs);
423
- if (config.aiKey) {
424
- console.log("\u{1F9E0} Fetching autonomous root-cause analysis from model...");
425
- rcaInsights = await fetchRcaInsights(semanticReport, config.aiKey);
426
- console.log("\u{1F4D6} Generating plain-English incident narrative...");
427
- incidentNarrative = await fetchIncidentNarrative(history, semanticReport, config.aiKey);
428
- }
429
336
  }
430
337
  const finalState = history[history.length - 1] || { apdex: 0, errorRate: 0, p95Latency: 0, throughput: 0 };
431
338
  const healthScore = computeHealthScoreValue(finalState.apdex, finalState.errorRate, finalState.p95Latency, config.maxAllowedLatencyMs);
@@ -451,7 +358,7 @@ async function runIntelligentAgenticStressTest(config) {
451
358
  Object.keys(globalCodeCounts).forEach((code) => {
452
359
  breakdownRates[code] = totalRequestsAccumulator === 0 ? 0 : globalCodeCounts[code] / totalRequestsAccumulator * 100;
453
360
  });
454
- exportHtmlDashboard(history, config, verdictReason, semanticReport, { total1xx, total2xx, total3xx, total4xx, total5xx, breakdownRates }, finalSummaryCards, lastRawRequests, rcaInsights, incidentNarrative);
361
+ exportHtmlDashboard(history, config, verdictReason, semanticReport, { total1xx, total2xx, total3xx, total4xx, total5xx, breakdownRates }, finalSummaryCards, lastRawRequests);
455
362
  }
456
363
  async function runStandardStressTest(config) {
457
364
  console.log(`\u{1F3CB}\uFE0F Running Standard Stress Test [Threads: ${config.threads} | Duration: ${config.durationSec}s]`);
@@ -470,19 +377,11 @@ async function runStandardStressTest(config) {
470
377
  failedRequests: metrics.c4xx + metrics.c5xx
471
378
  }];
472
379
  let semanticReport = null;
473
- let rcaInsights = "";
474
- let incidentNarrative = "";
475
380
  if (config.clusterLogs) {
476
381
  let errsToProcess = rawErrors;
477
382
  if (errsToProcess.length === 0) errsToProcess = getFallbackClusterLogs();
478
383
  const analyzer = new LogAnalyzer();
479
384
  semanticReport = analyzer.process(errsToProcess);
480
- if (config.aiKey) {
481
- console.log("\u{1F9E0} Fetching autonomous root-cause analysis from model...");
482
- rcaInsights = await fetchRcaInsights(semanticReport, config.aiKey);
483
- console.log("\u{1F4D6} Generating plain-English incident narrative...");
484
- incidentNarrative = await fetchIncidentNarrative(history, semanticReport, config.aiKey);
485
- }
486
385
  }
487
386
  const finalSummaryCards = {
488
387
  apdex: metrics.apdexScore,
@@ -513,7 +412,7 @@ async function runStandardStressTest(config) {
513
412
  total4xx: metrics.c4xx,
514
413
  total5xx: metrics.c5xx,
515
414
  breakdownRates
516
- }, finalSummaryCards, rawRequests, rcaInsights, incidentNarrative);
415
+ }, finalSummaryCards, rawRequests);
517
416
  }
518
417
  function getFallbackClusterLogs() {
519
418
  const logs = [];
@@ -568,7 +467,7 @@ function processMetricsTelemetry(requests, durationSec) {
568
467
  const avgTlsMs = mathUtils.mean(requests.map((r) => r.tlsTimeMs || 0));
569
468
  const avgTtfbMs = avgDnsMs + avgTcpMs + avgTlsMs + avgLatencyMs * 0.3;
570
469
  let c1xx = 0, c2xx = 0, c3xx = 0, c4xx = 0, c5xx = 0;
571
- const codeCounts = { 400: 0, 401: 0, 403: 0, 404: 0, 429: 0, 500: 502, 503: 0, 504: 0 };
470
+ const codeCounts = { 400: 0, 401: 0, 403: 0, 404: 0, 429: 0, 500: 0, 502: 0, 503: 0, 504: 0 };
572
471
  requests.forEach((r) => {
573
472
  if (r.statusCode >= 100 && r.statusCode < 200) c1xx++;
574
473
  else if (r.statusCode >= 200 && r.statusCode < 300) c2xx++;
@@ -629,7 +528,7 @@ function generateFinalAgentReport(history, score) {
629
528
  console.log(`\u26A1 Peak Achieved Cluster Velocity : ${peakThroughput.toFixed(0)} req/sec`);
630
529
  console.log("=======================================================\n");
631
530
  }
632
- function exportHtmlDashboard(history, config, verdictReason, semanticReport, responseMatrix, cards, rawRequests = [], rcaInsights = "", incidentNarrative = "") {
531
+ function exportHtmlDashboard(history, config, verdictReason, semanticReport, responseMatrix, cards, rawRequests = []) {
633
532
  const labels = history.map((h, i) => `${i + 1}s`);
634
533
  const successRequestsData = history.map((h) => h.successRequests);
635
534
  const failedWorkloadsData = history.map((h) => h.failedRequests);
@@ -646,26 +545,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
646
545
  x: Number(((r.timestampMs - firstTimestamp) / 1e3).toFixed(2)),
647
546
  y: Number(((r.dnsTimeMs || 0) + (r.tcpTimeMs || 0) + (r.tlsTimeMs || 0) + r.durationMs * 0.3).toFixed(1))
648
547
  }));
649
- let rcaAccordionHtml = "";
650
- if (config.clusterLogs) {
651
- const content = rcaInsights ? rcaInsights : `
652
- <div style="background: #090d16; padding: 1rem; border-radius: 6px; border: 1px dashed #475569; color: #94a3b8;">
653
- \u{1F4A1} <strong>Autonomous RCA Available:</strong> Pass the <code>--ai-key &lt;your-key&gt;</code> flag, or configure a <code>GEMINI_API_KEY</code> environment variable in your PowerShell runtime session to dynamically structure error logs here.
654
- </div>`;
655
- rcaAccordionHtml = `
656
- <details class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #8b5cf6; padding: 0; overflow: hidden;" open>
657
- <summary style="font-size: 1.2rem; font-weight: bold; color: #c084fc; padding: 1.25rem; display: flex; align-items: center; justify-content: space-between; cursor: pointer; outline: none; user-select: none; list-style: none;">
658
- <span style="display: flex; align-items: center; gap: 0.6rem;">\u{1F9E0} Autonomous Root-Cause Analysis (RCA) Insights</span>
659
- <span style="font-size: 0.8rem; color: #64748b; font-weight: normal; font-family: monospace;">[CLICK TO COLLAPSE/EXPAND]</span>
660
- </summary>
661
- <div style="padding: 0 1.25rem 1.25rem 1.25rem; border-top: 1px solid #1e293b; color: #cbd5e1; font-size: 0.95rem; line-height: 1.6;">
662
- <div style="margin-top: 1rem; margin-bottom: 0.5rem; color: #a78bfa; font-weight: 600;">System Diagnostic Summary:</div>
663
- <div style="padding-left: 0.5rem;">
664
- ${content}
665
- </div>
666
- </div>
667
- </details>`;
668
- }
669
548
  let logClustersHtml = "";
670
549
  if (semanticReport) {
671
550
  const totalLogCount = semanticReport.clusters.reduce((sum, c) => sum + c.count, 0);
@@ -673,7 +552,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
673
552
  logClustersHtml = `
674
553
  <div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
675
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;">
676
- \u{1F4CA} Semantic Log Clustering & Error Classification
555
+ \u{1F9E0} Semantic Log Clustering & Error Classification
677
556
  </h3>
678
557
  <div style="color: #94a3b8; font-size: 0.9rem; margin-bottom: 1.5rem;">
679
558
  Captured <strong style="color: #f8fafc;">${totalLogCount}</strong> raw failures grouped into <strong style="color: #f8fafc;">${uniquePatternsCount}</strong> unique structural patterns.
@@ -809,7 +688,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
809
688
  const htmlContent = `<!DOCTYPE html><html lang="en"><head>
810
689
  <meta charset="UTF-8">
811
690
  <title>Blaze Core Performance Report</title>
812
- <script src="[https://cdn.jsdelivr.net/npm/chart.js](https://cdn.jsdelivr.net/npm/chart.js)"></script>
691
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
813
692
  <style>
814
693
  body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0b111e; color: #f8fafc; margin: 0; padding: 2rem; }
815
694
  .container { max-width: 1300px; margin: 0 auto; }
@@ -862,12 +741,10 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
862
741
  .badge { padding: 0.25rem 0.5rem; border-radius: 4px; font-size: 0.8rem; font-weight: bold; }
863
742
  .badge-success { background: #16a34a; color: #f0fdf4; }
864
743
  .badge-fail { background: #dc2626; color: #fef2f2; }
865
-
866
- summary::-webkit-details-marker { display: none; }
867
744
  </style></head><body>
868
745
  <div class="container">
869
746
  <div class="header">
870
- <h1>\u{1F525} Blaze Core Performance Report</h1>
747
+ <h1>\u{1F525} Blaze Core Performance Analysis</h1>
871
748
  <div class="meta">Target Script: <code>${config.targetScript}</code></div>
872
749
  </div>
873
750
 
@@ -910,14 +787,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
910
787
  <div class="verdict-box">
911
788
  <div class="verdict-title">\u{1F916} AI Stress-Testing Agent Verdict</div>
912
789
  <div class="verdict-text">${verdictReason}</div>
913
-
914
- <!-- GENERATIVE INCIDENT NARRATIVE INJECTION PANEL -->
915
- ${incidentNarrative ? `
916
- <div style="margin-top: 1rem; margin-bottom: 1rem; padding: 1rem; background: rgba(56, 189, 248, 0.06); border-left: 4px solid #38bdf8; border-radius: 4px; font-size: 0.95rem; line-height: 1.6; color: #cbd5e1;">
917
- <strong style="color: #38bdf8; display: flex; align-items: center; gap: 0.4rem; margin-bottom: 0.5rem; text-transform: uppercase; font-size: 0.8rem; letter-spacing: 0.05em;">\u{1F4D6} Generative Incident Narrative:</strong>
918
- ${incidentNarrative}
919
- </div>` : ""}
920
-
921
790
  <div class="verdict-waves">${waveListItems}</div>
922
791
  </div>
923
792
 
@@ -1033,7 +902,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1033
902
  ${seoImpactSectionHtml}
1034
903
  ${liveAdjusterHtml}
1035
904
  ${rightSizingHtml}
1036
- ${rcaAccordionHtml}
1037
905
  ${logClustersHtml}
1038
906
  </div>
1039
907
 
@@ -1091,6 +959,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1091
959
  }
1092
960
  });
1093
961
 
962
+ // --- AI FORECASTING LINE REGRESSION SETUP ---
1094
963
  const baseActiveThreads = ${JSON.stringify(activeThreadsData)};
1095
964
  const baseTtfTrend = ${JSON.stringify(ttfTrendData)};
1096
965
  const historicalCount = baseTtfTrend.length;
@@ -1119,6 +988,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1119
988
  const lastThreads = baseActiveThreads[historicalCount - 1] || 10;
1120
989
  const threadStep = ${config.stepSize || 15};
1121
990
 
991
+ // Project out the next 3 hypothetical execution tiers
1122
992
  for (let i = 1; i <= 3; i++) {
1123
993
  extendedLabels.push(\`+\${i * 5}s (AI Forecast)\`);
1124
994
  extendedThreads.push(lastThreads + (threadStep * i));
@@ -1236,6 +1106,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1236
1106
  function printUsage() {
1237
1107
  console.log(`Blaze Core Performance Test CLI Engine
1238
1108
  Options:
1239
- --threads <count> | --duration <seconds> | --agentic | --cluster-logs | --correlate | --seo | --ai-key <api-key>`);
1109
+ --threads <count> | --duration <seconds> | --agentic | --cluster-logs | --correlate | --seo`);
1240
1110
  }
1241
1111
  main().catch(console.error);
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blaze-performance-tester",
3
- "version": "3.1.31",
3
+ "version": "3.1.33",
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",