blaze-performance-tester 3.2.3 → 3.2.4
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 +5 -113
- package/dist/index.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -196,94 +196,6 @@ function loadBaselineData(filePath) {
|
|
|
196
196
|
}
|
|
197
197
|
return null;
|
|
198
198
|
}
|
|
199
|
-
async function generateScenarioTS(prompt) {
|
|
200
|
-
const apiKey = process.env.GEMINI_API_KEY;
|
|
201
|
-
if (!apiKey) {
|
|
202
|
-
throw new Error("\u274C Environment variable GEMINI_API_KEY is missing. AI scenario generation aborted.");
|
|
203
|
-
}
|
|
204
|
-
console.log("\u{1F9E0} Translating natural language requirements into TypeScript via Gemini 2.5 Flash...");
|
|
205
|
-
const systemInstruction = `
|
|
206
|
-
You are an expert Performance & Systems Reliability Engineer specializing in QuickJS-compatible virtual user load testing scripts for the Blaze framework.
|
|
207
|
-
Your task is to convert a natural language description into a clean, valid TypeScript simulation script.
|
|
208
|
-
|
|
209
|
-
The script must adhere to this exact structural import pattern:
|
|
210
|
-
\`\`\`typescript
|
|
211
|
-
import { VirtualUser } from '../src/core/vu';
|
|
212
|
-
|
|
213
|
-
export async function runScenario(vu: VirtualUser) {
|
|
214
|
-
// Setup headers
|
|
215
|
-
// Execute multi-step operations (e.g., fetching a login, parsing tokens, making subsequent requests)
|
|
216
|
-
// Manage dynamic value extraction (e.g., const token = response.json().token) and pass variables forward
|
|
217
|
-
// Include standard loops (e.g., for-loops) or timeouts as requested
|
|
218
|
-
}
|
|
219
|
-
\`\`\`
|
|
220
|
-
|
|
221
|
-
Rules:
|
|
222
|
-
1. Return ONLY executable, valid TypeScript script.
|
|
223
|
-
2. Cleanly extract dynamic payload fields or tokens and assign them to downstream headers.
|
|
224
|
-
3. Keep logic performance-optimized and sandbox-compatible.
|
|
225
|
-
4. Do NOT wrap code blocks in backticks like \`\`\`typescript. Start directly with the TypeScript imports and export block. Do not include markdown or text commentary.
|
|
226
|
-
`;
|
|
227
|
-
try {
|
|
228
|
-
const endpoint = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=" + apiKey;
|
|
229
|
-
const response = await fetch(endpoint, {
|
|
230
|
-
method: "POST",
|
|
231
|
-
headers: { "Content-Type": "application/json" },
|
|
232
|
-
body: JSON.stringify({
|
|
233
|
-
contents: [{ parts: [{ text: `Generate a Virtual User script for this scenario: ${prompt}` }] }],
|
|
234
|
-
generationConfig: {
|
|
235
|
-
temperature: 0.1,
|
|
236
|
-
maxOutputTokens: 65536
|
|
237
|
-
},
|
|
238
|
-
systemInstruction: {
|
|
239
|
-
parts: [{ text: systemInstruction }]
|
|
240
|
-
}
|
|
241
|
-
})
|
|
242
|
-
});
|
|
243
|
-
const data = await response.json();
|
|
244
|
-
if (data?.error) {
|
|
245
|
-
throw new Error(`Google API Error ${data.error.code}: ${data.error.message}`);
|
|
246
|
-
}
|
|
247
|
-
const candidateText = data?.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
248
|
-
if (!candidateText) {
|
|
249
|
-
throw new Error(`Malformed API layout or empty response body.`);
|
|
250
|
-
}
|
|
251
|
-
return candidateText.replace(/```typescript/g, "").replace(/```javascript/g, "").replace(/```/g, "").trim();
|
|
252
|
-
} catch (error) {
|
|
253
|
-
throw new Error(`Failed to generate script via Gemini: ${error.message || error}`);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
async function handleScenarioGeneration(config) {
|
|
257
|
-
const targetDir = path.resolve(__dirname, "./tests");
|
|
258
|
-
const tsFilePath = path.join(targetDir, "generated_scenario.ts");
|
|
259
|
-
const jsFilePath = path.join(targetDir, "generated_scenario.js");
|
|
260
|
-
try {
|
|
261
|
-
if (!fs.existsSync(targetDir)) {
|
|
262
|
-
fs.mkdirSync(targetDir, { recursive: true });
|
|
263
|
-
}
|
|
264
|
-
const tsCode = await generateScenarioTS(config.scenarioPrompt);
|
|
265
|
-
fs.writeFileSync(tsFilePath, tsCode, "utf-8");
|
|
266
|
-
console.log(`\u{1F4BE} Successfully generated scenario script saved to: ${tsFilePath}`);
|
|
267
|
-
console.log("\u2699\uFE0F Transpiling generated scenario to JavaScript for native QuickJS sandbox validation...");
|
|
268
|
-
let compiledSuccessfully = false;
|
|
269
|
-
try {
|
|
270
|
-
const { execSync } = require2("child_process");
|
|
271
|
-
execSync(`npx tsc "${tsFilePath}" --target es2020 --module commonjs --allowJs --skipLibCheck`, { stdio: "ignore" });
|
|
272
|
-
compiledSuccessfully = true;
|
|
273
|
-
} catch (e) {
|
|
274
|
-
console.warn("\u26A0\uFE0F TypeScript compiler (tsc) was not found or timed out. Falling back to clean JS copy conversion...");
|
|
275
|
-
}
|
|
276
|
-
if (!compiledSuccessfully) {
|
|
277
|
-
const cleanJs = tsCode.replace(/: VirtualUser/g, "").replace(/import {[^}]+} from .*/g, "").replace(/export async/g, "async");
|
|
278
|
-
fs.writeFileSync(jsFilePath, cleanJs, "utf-8");
|
|
279
|
-
}
|
|
280
|
-
console.log(`\u2705 Sandbox compilation resolved. Active test file: ${jsFilePath}`);
|
|
281
|
-
config.targetScript = jsFilePath;
|
|
282
|
-
} catch (error) {
|
|
283
|
-
console.error(`\u274C Scenario generation flow aborted: ${error.message || error}`);
|
|
284
|
-
process.exit(1);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
199
|
async function generateGeminiRCA(history, finalSummary, errorLogs) {
|
|
288
200
|
const apiKey = process.env.GEMINI_API_KEY;
|
|
289
201
|
if (!apiKey) {
|
|
@@ -313,15 +225,14 @@ Provide a comprehensive, highly technical Root Cause Analysis (RCA) report struc
|
|
|
313
225
|
|
|
314
226
|
Paragraph 1 - GENERATIVE INCIDENT NARRATIVE: Write a clean, plain-English story of the incident that builds a chronological timeline of the failure event (e.g., "At 00:12s, traffic spiked by 40%. This caused database connection pool exhaustion, which triggered a cascading series of 504 errors on the checkout endpoint, ultimately hitting a knee-point crash at 500 virtual users."). Translate raw logs and metrics trends directly into an easy-to-read chronological story.
|
|
315
227
|
|
|
316
|
-
Paragraph 2 - TECHNICAL BOTTLENECK
|
|
228
|
+
Paragraph 2 - TECHNICAL BOTTLENECK DIAGNOSIS: Diagnose the exact bottleneck point (CPU saturation, socket pool exhaustion, database lock contention, etc.) indicated by how latency changes dynamically alongside concurrency, and correlate unique structural exception/error patterns directly to the performance drops.
|
|
317
229
|
|
|
318
230
|
Paragraph 3 - ARCHITECTURAL SIZING RECOMMENDATIONS: Give concrete, infrastructure sizing or cloud architecture remediation recommendations based on the stress points found.
|
|
319
231
|
|
|
320
232
|
CRITICAL: Return ONLY plain paragraph text. Do not use markdown headers (###). If you use bold text, use standard HTML <strong> tags. Wrap lines cleanly.
|
|
321
233
|
`;
|
|
322
234
|
try {
|
|
323
|
-
const
|
|
324
|
-
const response = await fetch(endpoint, {
|
|
235
|
+
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=${apiKey}`, {
|
|
325
236
|
method: "POST",
|
|
326
237
|
headers: { "Content-Type": "application/json" },
|
|
327
238
|
body: JSON.stringify({
|
|
@@ -389,9 +300,6 @@ async function main() {
|
|
|
389
300
|
return;
|
|
390
301
|
}
|
|
391
302
|
const config = parseArguments(args);
|
|
392
|
-
if (config.scenarioPrompt) {
|
|
393
|
-
await handleScenarioGeneration(config);
|
|
394
|
-
}
|
|
395
303
|
if (config.isCorrelate) {
|
|
396
304
|
await executeTestPipeline(config);
|
|
397
305
|
}
|
|
@@ -402,12 +310,6 @@ async function main() {
|
|
|
402
310
|
}
|
|
403
311
|
}
|
|
404
312
|
function parseArguments(args) {
|
|
405
|
-
const scenarioIdx = args.indexOf("--generate-scenario");
|
|
406
|
-
let scenarioPrompt = null;
|
|
407
|
-
if (scenarioIdx !== -1) {
|
|
408
|
-
scenarioPrompt = args[scenarioIdx + 1];
|
|
409
|
-
args.splice(scenarioIdx, 2);
|
|
410
|
-
}
|
|
411
313
|
const targetScript = path.resolve(args[0] || ".");
|
|
412
314
|
const isAgentic = args.includes("--agentic");
|
|
413
315
|
const isCorrelate = args.includes("--correlate");
|
|
@@ -461,7 +363,6 @@ function parseArguments(args) {
|
|
|
461
363
|
}
|
|
462
364
|
return {
|
|
463
365
|
targetScript,
|
|
464
|
-
scenarioPrompt,
|
|
465
366
|
isAgentic,
|
|
466
367
|
isCorrelate,
|
|
467
368
|
isSeo,
|
|
@@ -1062,11 +963,10 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
1062
963
|
`;
|
|
1063
964
|
}).join("");
|
|
1064
965
|
const gaugeColor = cards.healthScore >= 90 ? "#10b981" : cards.healthScore >= 70 ? "#f59e0b" : "#ef4444";
|
|
1065
|
-
const chartJsCdn = "https://cdn.jsdelivr.net/npm/chart.js";
|
|
1066
966
|
const htmlContent = `<!DOCTYPE html><html lang="en"><head>
|
|
1067
967
|
<meta charset="UTF-8">
|
|
1068
968
|
<title>Blaze Core Performance Report</title>
|
|
1069
|
-
<script src="
|
|
969
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
1070
970
|
<style>
|
|
1071
971
|
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0b111e; color: #f8fafc; margin: 0; padding: 2rem; }
|
|
1072
972
|
.container { max-width: 1300px; margin: 0 auto; }
|
|
@@ -1122,7 +1022,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
1122
1022
|
</style></head><body>
|
|
1123
1023
|
<div class="container">
|
|
1124
1024
|
<div class="header">
|
|
1125
|
-
<h1>\u{1F525} Blaze Core Performance
|
|
1025
|
+
<h1>\u{1F525} Blaze Core Performance Analysis</h1>
|
|
1126
1026
|
<div class="meta">Target Script: <code>${config.targetScript}</code> | Ramp-Up: ${config.rampUpSec}s | Ramp-Down: ${config.rampDownSec}s</div>
|
|
1127
1027
|
</div>
|
|
1128
1028
|
|
|
@@ -1559,14 +1459,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
1559
1459
|
function printUsage() {
|
|
1560
1460
|
console.log(`Blaze Core Performance Test CLI Engine
|
|
1561
1461
|
Options:
|
|
1562
|
-
--
|
|
1563
|
-
--threads <count> Number of concurrent threads (default: 10)
|
|
1564
|
-
--duration <seconds> Duration of stress testing in seconds (default: 10)
|
|
1565
|
-
--ramp-up <seconds> Ramp-up speed
|
|
1566
|
-
--ramp-down <seconds> Ramp-down speed
|
|
1567
|
-
--agentic Enable Intelligent Autonomous Agentic Stress Test
|
|
1568
|
-
--correlate Launch dynamic transaction parameter mapping pipeline
|
|
1569
|
-
--baseline <json_file> Input baseline JSON benchmark reference
|
|
1570
|
-
--output <html_file> Target path for exported standalone dashboard`);
|
|
1462
|
+
--threads <count> | --duration <seconds> | --baseline <json_file> | --output <html_file>`);
|
|
1571
1463
|
}
|
|
1572
1464
|
main().catch(console.error);
|
|
Binary file
|