blaze-performance-tester 3.1.28 → 3.1.29

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,6 +87,45 @@ 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://api.openai.com/v1/chat/completions", {
97
+ method: "POST",
98
+ headers: {
99
+ "Content-Type": "application/json",
100
+ "Authorization": `Bearer ${apiKey}`
101
+ },
102
+ body: JSON.stringify({
103
+ model: "gpt-4o-mini",
104
+ messages: [
105
+ {
106
+ role: "system",
107
+ content: "You are a principal systems architect and site reliability engineer. Return clean, direct HTML list items (\u7528 <li> tags, no raw markdown blocks) summarizing diagnostics."
108
+ },
109
+ {
110
+ role: "user",
111
+ content: `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.
112
+
113
+ Error Log Patterns:
114
+ ${errorSummary}`
115
+ }
116
+ ],
117
+ temperature: 0.2
118
+ })
119
+ });
120
+ if (!response.ok) {
121
+ return `<span style="color: #ef4444;">AI Completion API Error: ${response.status} ${response.statusText}</span>`;
122
+ }
123
+ const data = await response.json();
124
+ return data.choices?.[0]?.message?.content || "<li>Failed to aggregate autonomous analysis parameters.</li>";
125
+ } catch (error) {
126
+ return `<span style="color: #ef4444;">Failed to resolve external cloud model: ${error.message}</span>`;
127
+ }
128
+ }
90
129
  async function executeTestPipeline(config) {
91
130
  if (!blazeCore || typeof blazeCore.runCorrelatedTransaction !== "function") {
92
131
  console.error("\u274C Error: runCorrelatedTransaction function is missing from the compiled binary bindings.");
@@ -148,6 +187,7 @@ function parseArguments(args) {
148
187
  let maxThreads = 300;
149
188
  let maxAllowedLatencyMs = 800;
150
189
  let outputHtml = "blaze-dashboard.html";
190
+ let aiKey = "";
151
191
  const threadsIdx = args.indexOf("--threads");
152
192
  if (threadsIdx !== -1) threads = parseInt(args[threadsIdx + 1], 10);
153
193
  const durationIdx = args.indexOf("--duration");
@@ -160,6 +200,8 @@ function parseArguments(args) {
160
200
  if (maxThreadsIdx !== -1) maxThreads = parseInt(args[maxThreadsIdx + 1], 10);
161
201
  const outputIdx = args.indexOf("--output");
162
202
  if (outputIdx !== -1) outputHtml = args[outputIdx + 1];
203
+ const aiKeyIdx = args.indexOf("--ai-key");
204
+ if (aiKeyIdx !== -1) aiKey = args[aiKeyIdx + 1];
163
205
  const positionalNums = args.slice(1).filter((arg) => !arg.startsWith("-")).map(Number).filter((n) => !isNaN(n));
164
206
  if (positionalNums.length > 0 && threadsIdx === -1 && !isAgentic) threads = positionalNums[0];
165
207
  if (positionalNums.length > 1 && durationIdx === -1 && !isAgentic) durationSec = positionalNums[1];
@@ -191,7 +233,8 @@ function parseArguments(args) {
191
233
  maxThreads,
192
234
  stepSize: 15,
193
235
  maxAllowedLatencyMs,
194
- outputHtml
236
+ outputHtml,
237
+ aiKey
195
238
  };
196
239
  }
197
240
  async function runBlazeCoreEngine(config) {
@@ -327,12 +370,17 @@ async function runIntelligentAgenticStressTest(config) {
327
370
  currentThreads += nextStep;
328
371
  }
329
372
  let semanticReport = null;
373
+ let rcaInsights = "";
330
374
  if (config.clusterLogs) {
331
375
  if (aggregateErrorLogs.length === 0) {
332
376
  aggregateErrorLogs = getFallbackClusterLogs();
333
377
  }
334
378
  const analyzer = new LogAnalyzer();
335
379
  semanticReport = analyzer.process(aggregateErrorLogs);
380
+ if (config.aiKey) {
381
+ console.log("\u{1F9E0} Fetching autonomous root-cause analysis from model...");
382
+ rcaInsights = await fetchRcaInsights(semanticReport, config.aiKey);
383
+ }
336
384
  }
337
385
  const finalState = history[history.length - 1] || { apdex: 0, errorRate: 0, p95Latency: 0, throughput: 0 };
338
386
  const healthScore = computeHealthScoreValue(finalState.apdex, finalState.errorRate, finalState.p95Latency, config.maxAllowedLatencyMs);
@@ -358,7 +406,7 @@ async function runIntelligentAgenticStressTest(config) {
358
406
  Object.keys(globalCodeCounts).forEach((code) => {
359
407
  breakdownRates[code] = totalRequestsAccumulator === 0 ? 0 : globalCodeCounts[code] / totalRequestsAccumulator * 100;
360
408
  });
361
- exportHtmlDashboard(history, config, verdictReason, semanticReport, { total1xx, total2xx, total3xx, total4xx, total5xx, breakdownRates }, finalSummaryCards, lastRawRequests);
409
+ exportHtmlDashboard(history, config, verdictReason, semanticReport, { total1xx, total2xx, total3xx, total4xx, total5xx, breakdownRates }, finalSummaryCards, lastRawRequests, rcaInsights);
362
410
  }
363
411
  async function runStandardStressTest(config) {
364
412
  console.log(`\u{1F3CB}\uFE0F Running Standard Stress Test [Threads: ${config.threads} | Duration: ${config.durationSec}s]`);
@@ -377,11 +425,16 @@ async function runStandardStressTest(config) {
377
425
  failedRequests: metrics.c4xx + metrics.c5xx
378
426
  }];
379
427
  let semanticReport = null;
428
+ let rcaInsights = "";
380
429
  if (config.clusterLogs) {
381
430
  let errsToProcess = rawErrors;
382
431
  if (errsToProcess.length === 0) errsToProcess = getFallbackClusterLogs();
383
432
  const analyzer = new LogAnalyzer();
384
433
  semanticReport = analyzer.process(errsToProcess);
434
+ if (config.aiKey) {
435
+ console.log("\u{1F9E0} Fetching autonomous root-cause analysis from model...");
436
+ rcaInsights = await fetchRcaInsights(semanticReport, config.aiKey);
437
+ }
385
438
  }
386
439
  const finalSummaryCards = {
387
440
  apdex: metrics.apdexScore,
@@ -412,7 +465,7 @@ async function runStandardStressTest(config) {
412
465
  total4xx: metrics.c4xx,
413
466
  total5xx: metrics.c5xx,
414
467
  breakdownRates
415
- }, finalSummaryCards, rawRequests);
468
+ }, finalSummaryCards, rawRequests, rcaInsights);
416
469
  }
417
470
  function getFallbackClusterLogs() {
418
471
  const logs = [];
@@ -528,7 +581,7 @@ function generateFinalAgentReport(history, score) {
528
581
  console.log(`\u26A1 Peak Achieved Cluster Velocity : ${peakThroughput.toFixed(0)} req/sec`);
529
582
  console.log("=======================================================\n");
530
583
  }
531
- function exportHtmlDashboard(history, config, verdictReason, semanticReport, responseMatrix, cards, rawRequests = []) {
584
+ function exportHtmlDashboard(history, config, verdictReason, semanticReport, responseMatrix, cards, rawRequests = [], rcaInsights = "") {
532
585
  const labels = history.map((h, i) => `${i + 1}s`);
533
586
  const successRequestsData = history.map((h) => h.successRequests);
534
587
  const failedWorkloadsData = history.map((h) => h.failedRequests);
@@ -545,6 +598,26 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
545
598
  x: Number(((r.timestampMs - firstTimestamp) / 1e3).toFixed(2)),
546
599
  y: Number(((r.dnsTimeMs || 0) + (r.tcpTimeMs || 0) + (r.tlsTimeMs || 0) + r.durationMs * 0.3).toFixed(1))
547
600
  }));
601
+ let rcaAccordionHtml = "";
602
+ if (config.clusterLogs) {
603
+ const content = rcaInsights ? rcaInsights : `
604
+ <div style="background: #090d16; padding: 1rem; border-radius: 6px; border: 1px dashed #475569; color: #94a3b8;">
605
+ \u{1F4A1} <strong>Autonomous RCA Available:</strong> Pass the <code>--ai-key &lt;your-key&gt;</code> flag during pipeline execution to automatically turn structural failure logs into actionable configuration mitigations here.
606
+ </div>`;
607
+ rcaAccordionHtml = `
608
+ <details class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #8b5cf6; padding: 0; overflow: hidden;" open>
609
+ <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;">
610
+ <span style="display: flex; align-items: center; gap: 0.6rem;">\u{1F9E0} Autonomous Root-Cause Analysis (RCA) Insights</span>
611
+ <span style="font-size: 0.8rem; color: #64748b; font-weight: normal; font-family: monospace;">[CLICK TO COLLAPSE/EXPAND]</span>
612
+ </summary>
613
+ <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;">
614
+ <div style="margin-top: 1rem; margin-bottom: 0.5rem; color: #a78bfa; font-weight: 600;">System Diagnostic Summary:</div>
615
+ <div style="padding-left: 0.5rem;">
616
+ ${content}
617
+ </div>
618
+ </div>
619
+ </details>`;
620
+ }
548
621
  let logClustersHtml = "";
549
622
  if (semanticReport) {
550
623
  const totalLogCount = semanticReport.clusters.reduce((sum, c) => sum + c.count, 0);
@@ -552,7 +625,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
552
625
  logClustersHtml = `
553
626
  <div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #1e293b;">
554
627
  <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
- \u{1F9E0} Semantic Log Clustering & Error Classification
628
+ \u{1F4CA} Semantic Log Clustering & Error Classification
556
629
  </h3>
557
630
  <div style="color: #94a3b8; font-size: 0.9rem; margin-bottom: 1.5rem;">
558
631
  Captured <strong style="color: #f8fafc;">${totalLogCount}</strong> raw failures grouped into <strong style="color: #f8fafc;">${uniquePatternsCount}</strong> unique structural patterns.
@@ -741,6 +814,8 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
741
814
  .badge { padding: 0.25rem 0.5rem; border-radius: 4px; font-size: 0.8rem; font-weight: bold; }
742
815
  .badge-success { background: #16a34a; color: #f0fdf4; }
743
816
  .badge-fail { background: #dc2626; color: #fef2f2; }
817
+
818
+ summary::-webkit-details-marker { display: none; }
744
819
  </style></head><body>
745
820
  <div class="container">
746
821
  <div class="header">
@@ -902,6 +977,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
902
977
  ${seoImpactSectionHtml}
903
978
  ${liveAdjusterHtml}
904
979
  ${rightSizingHtml}
980
+ ${rcaAccordionHtml}
905
981
  ${logClustersHtml}
906
982
  </div>
907
983
 
@@ -959,7 +1035,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
959
1035
  }
960
1036
  });
961
1037
 
962
- // --- AI FORECASTING LINE REGRESSION SETUP ---
963
1038
  const baseActiveThreads = ${JSON.stringify(activeThreadsData)};
964
1039
  const baseTtfTrend = ${JSON.stringify(ttfTrendData)};
965
1040
  const historicalCount = baseTtfTrend.length;
@@ -988,7 +1063,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
988
1063
  const lastThreads = baseActiveThreads[historicalCount - 1] || 10;
989
1064
  const threadStep = ${config.stepSize || 15};
990
1065
 
991
- // Project out the next 3 hypothetical execution tiers
992
1066
  for (let i = 1; i <= 3; i++) {
993
1067
  extendedLabels.push(\`+\${i * 5}s (AI Forecast)\`);
994
1068
  extendedThreads.push(lastThreads + (threadStep * i));
@@ -1106,6 +1180,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1106
1180
  function printUsage() {
1107
1181
  console.log(`Blaze Core Performance Test CLI Engine
1108
1182
  Options:
1109
- --threads <count> | --duration <seconds> | --agentic | --cluster-logs | --correlate | --seo`);
1183
+ --threads <count> | --duration <seconds> | --agentic | --cluster-logs | --correlate | --seo | --ai-key <api-key>`);
1110
1184
  }
1111
1185
  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.28",
3
+ "version": "3.1.29",
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",