blaze-performance-tester 3.1.35 → 3.1.36
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 +68 -10
- package/dist/index.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -87,6 +87,54 @@ var mathUtils = {
|
|
|
87
87
|
return sorted[Math.max(0, index)];
|
|
88
88
|
}
|
|
89
89
|
};
|
|
90
|
+
async function generateGeminiRCA(history, finalSummary, errorLogs) {
|
|
91
|
+
const apiKey = process.env.GEMINI_API_KEY;
|
|
92
|
+
if (!apiKey) {
|
|
93
|
+
return `<span style="color: #ef4444;">\u26A0\uFE0F Gemini API Key missing. Export GEMINI_API_KEY to enable automated 2.5 Flash RCA analysis.</span>`;
|
|
94
|
+
}
|
|
95
|
+
console.log("\u{1F9E0} Querying Gemini 2.5 Flash for Advanced Root Cause Analysis...");
|
|
96
|
+
const formattedHistory = history.map(
|
|
97
|
+
(h) => `Threads: ${h.threads} VUs | Throughput: ${h.throughput.toFixed(1)} req/s | Avg Latency: ${h.avgLatency.toFixed(1)}ms | Errors: ${(h.errorRate * 100).toFixed(2)}% | Apdex: ${h.apdex.toFixed(2)}`
|
|
98
|
+
).join("\n");
|
|
99
|
+
const uniqueLogs = Array.from(new Set(errorLogs)).slice(0, 10).join("\n");
|
|
100
|
+
const prompt = `
|
|
101
|
+
You are an expert Performance & Systems Reliability Engineer. Analyze the following load test execution telemetry and logs:
|
|
102
|
+
|
|
103
|
+
[LOAD SUMMARY METERICS]
|
|
104
|
+
- Unified Blaze Health Score: ${finalSummary.healthScore}/100
|
|
105
|
+
- Saturation Knee Point: ${finalSummary.saturationKneePoint} VUs
|
|
106
|
+
- Peak Stability Variance (Std Dev): ${finalSummary.stdDev.toFixed(2)}ms
|
|
107
|
+
- Network Bandwidth: ${finalSummary.bandwidth.toFixed(2)} MB/s
|
|
108
|
+
|
|
109
|
+
[EXECUTION STEP HISTORY]
|
|
110
|
+
${formattedHistory}
|
|
111
|
+
|
|
112
|
+
[UNIQUE LOG SAMPLES EXPLORATION]
|
|
113
|
+
${uniqueLogs || "No unique structural exceptions encountered."}
|
|
114
|
+
|
|
115
|
+
Provide a punchy, highly technical 3-paragraph Root Cause Analysis (RCA) report.
|
|
116
|
+
Paragraph 1: Diagnose the exact bottleneck point (CPU saturation, socket pool exhaustion, database lock contention, etc.) indicated by how latency changes with concurrency.
|
|
117
|
+
Paragraph 2: Correlate unique error patterns directly to performance drops.
|
|
118
|
+
Paragraph 3: Give concrete, actionable infrastructure or architectural sizing recommendations. Do not use markdown headers inside your response, use standard HTML bold text if needed, and wrap lines cleanly.
|
|
119
|
+
`;
|
|
120
|
+
try {
|
|
121
|
+
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=${apiKey}`, {
|
|
122
|
+
method: "POST",
|
|
123
|
+
headers: { "Content-Type": "application/json" },
|
|
124
|
+
body: JSON.stringify({
|
|
125
|
+
contents: [{ parts: [{ text: prompt }] }],
|
|
126
|
+
generationConfig: { temperature: 0.2, maxOutputTokens: 800 }
|
|
127
|
+
})
|
|
128
|
+
});
|
|
129
|
+
const data = await response.json();
|
|
130
|
+
const candidateText = data?.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
131
|
+
if (!candidateText) throw new Error("Malformed API structural response layout");
|
|
132
|
+
return candidateText.replace(/\n/g, "<br>");
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error("\u274C Gemini API processing breakdown failure:", error);
|
|
135
|
+
return `<span style="color: #f87171;">Failed to generate AI diagnosis framework: ${error.message}</span>`;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
90
138
|
async function executeTestPipeline(config) {
|
|
91
139
|
if (!blazeCore || typeof blazeCore.runCorrelatedTransaction !== "function") {
|
|
92
140
|
console.error("\u274C Error: runCorrelatedTransaction function is missing from the compiled binary bindings.");
|
|
@@ -334,7 +382,7 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
334
382
|
const analyzer = new LogAnalyzer();
|
|
335
383
|
semanticReport = analyzer.process(aggregateErrorLogs);
|
|
336
384
|
}
|
|
337
|
-
const finalState = history[history.length - 1] || { apdex: 0, errorRate: 0, p95Latency: 0, throughput: 0
|
|
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);
|
|
339
387
|
const finalSummaryCards = {
|
|
340
388
|
apdex: finalState.apdex,
|
|
@@ -349,17 +397,17 @@ async function runIntelligentAgenticStressTest(config) {
|
|
|
349
397
|
healthScore
|
|
350
398
|
};
|
|
351
399
|
generateFinalAgentReport(history, healthScore);
|
|
400
|
+
const geminiAnalysisHtml = await generateGeminiRCA(history, finalSummaryCards, aggregateErrorLogs);
|
|
352
401
|
if (config.isSeo) {
|
|
353
402
|
const finalLat = finalState.avgLatency || finalSummaryCards.ttfb;
|
|
354
403
|
const seo = calculateSeoImpactMetrics(finalLat);
|
|
355
404
|
console.log(`\u{1F50E} [SEO Impact Report]: Target latency under stress (${finalLat.toFixed(1)}ms) triggers a predicted Search Visibility Loss of -${seo.trafficLoss}% [Status: ${seo.status}].`);
|
|
356
405
|
}
|
|
357
406
|
const breakdownRates = {};
|
|
358
|
-
Object.keys(globalCodeCounts).forEach((
|
|
359
|
-
const code = parseInt(codeStr, 10);
|
|
407
|
+
Object.keys(globalCodeCounts).forEach((code) => {
|
|
360
408
|
breakdownRates[code] = totalRequestsAccumulator === 0 ? 0 : globalCodeCounts[code] / totalRequestsAccumulator * 100;
|
|
361
409
|
});
|
|
362
|
-
exportHtmlDashboard(history, config, verdictReason, semanticReport, { total1xx, total2xx, total3xx, total4xx, total5xx, breakdownRates }, finalSummaryCards, lastRawRequests);
|
|
410
|
+
exportHtmlDashboard(history, config, verdictReason, semanticReport, { total1xx, total2xx, total3xx, total4xx, total5xx, breakdownRates }, finalSummaryCards, lastRawRequests, geminiAnalysisHtml);
|
|
363
411
|
}
|
|
364
412
|
async function runStandardStressTest(config) {
|
|
365
413
|
console.log(`\u{1F3CB}\uFE0F Running Standard Stress Test [Threads: ${config.threads} | Duration: ${config.durationSec}s]`);
|
|
@@ -398,13 +446,13 @@ async function runStandardStressTest(config) {
|
|
|
398
446
|
};
|
|
399
447
|
const isPassed = metrics.apdexScore >= config.targetApdex && metrics.errorRate <= config.targetErrorRate;
|
|
400
448
|
const verdictReason = isPassed ? "Static single-wave baseline checks concluded successfully without triggering health boundaries." : "Static verification loop completed with values exceeding defined quality thresholds.";
|
|
449
|
+
const geminiAnalysisHtml = await generateGeminiRCA(history, finalSummaryCards, rawErrors.length > 0 ? rawErrors : getFallbackClusterLogs());
|
|
401
450
|
if (config.isSeo) {
|
|
402
451
|
const seo = calculateSeoImpactMetrics(metrics.avgLatencyMs);
|
|
403
452
|
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}].`);
|
|
404
453
|
}
|
|
405
454
|
const breakdownRates = {};
|
|
406
|
-
Object.keys(metrics.codeCounts).forEach((
|
|
407
|
-
const code = parseInt(codeStr, 10);
|
|
455
|
+
Object.keys(metrics.codeCounts).forEach((code) => {
|
|
408
456
|
breakdownRates[code] = metrics.totalRequests === 0 ? 0 : metrics.codeCounts[code] / metrics.totalRequests * 100;
|
|
409
457
|
});
|
|
410
458
|
exportHtmlDashboard(history, config, verdictReason, semanticReport, {
|
|
@@ -414,7 +462,7 @@ async function runStandardStressTest(config) {
|
|
|
414
462
|
total4xx: metrics.c4xx,
|
|
415
463
|
total5xx: metrics.c5xx,
|
|
416
464
|
breakdownRates
|
|
417
|
-
}, finalSummaryCards, rawRequests);
|
|
465
|
+
}, finalSummaryCards, rawRequests, geminiAnalysisHtml);
|
|
418
466
|
}
|
|
419
467
|
function getFallbackClusterLogs() {
|
|
420
468
|
const logs = [];
|
|
@@ -530,7 +578,7 @@ function generateFinalAgentReport(history, score) {
|
|
|
530
578
|
console.log(`\u26A1 Peak Achieved Cluster Velocity : ${peakThroughput.toFixed(0)} req/sec`);
|
|
531
579
|
console.log("=======================================================\n");
|
|
532
580
|
}
|
|
533
|
-
function exportHtmlDashboard(history, config, verdictReason, semanticReport, responseMatrix, cards, rawRequests = []) {
|
|
581
|
+
function exportHtmlDashboard(history, config, verdictReason, semanticReport, responseMatrix, cards, rawRequests = [], geminiAnalysisHtml = "") {
|
|
534
582
|
const labels = history.map((h, i) => `${i + 1}s`);
|
|
535
583
|
const successRequestsData = history.map((h) => h.successRequests);
|
|
536
584
|
const failedWorkloadsData = history.map((h) => h.failedRequests);
|
|
@@ -843,6 +891,16 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
843
891
|
</div>
|
|
844
892
|
</div>
|
|
845
893
|
|
|
894
|
+
<!-- Live Gemini 2.5 Flash Autonomous RCA Module -->
|
|
895
|
+
<div class="card" style="margin-bottom: 2rem; background: #0c172b; border: 1px solid #7c3aed;">
|
|
896
|
+
<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;">
|
|
897
|
+
\u26A1 Gemini 2.5 Flash Autonomous Root Cause Analysis (RCA)
|
|
898
|
+
</h3>
|
|
899
|
+
<div style="font-size: 0.95rem; line-height: 1.6; color: #cbd5e1; padding: 0.5rem 0;">
|
|
900
|
+
${geminiAnalysisHtml}
|
|
901
|
+
</div>
|
|
902
|
+
</div>
|
|
903
|
+
|
|
846
904
|
<div class="charts-grid">
|
|
847
905
|
<div class="graph-card">
|
|
848
906
|
<div class="graph-title">\u{1F4CA} Throughput Velocity & Workload Volume</div>
|
|
@@ -1047,8 +1105,8 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
1047
1105
|
},
|
|
1048
1106
|
scales: {
|
|
1049
1107
|
x: { grid: { color: '#1e293b' }, ticks: { color: '#64748b' } },
|
|
1050
|
-
|
|
1051
|
-
|
|
1108
|
+
y_threads: { position: 'left', grid: { color: '#1e293b' }, ticks: { color: '#38bdf8' }, title: { display: true, text: 'VUs / Threads', color: '#38bdf8' } },
|
|
1109
|
+
y_ttf: { position: 'right', grid: { drawOnChartArea: false }, ticks: { color: '#f43f5e' }, title: { display: true, text: 'TTF Index / Latency ms', color: '#f43f5e' } }
|
|
1052
1110
|
}
|
|
1053
1111
|
}
|
|
1054
1112
|
});
|
|
Binary file
|