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 +82 -8
- package/dist/index.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
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 <your-key></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{
|
|
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
|