blaze-performance-tester 3.2.3 → 3.2.5
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 +101 -126
- 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({
|
|
@@ -350,31 +261,108 @@ CRITICAL: Return ONLY plain paragraph text. Do not use markdown headers (###). I
|
|
|
350
261
|
return `<span style="color: #f87171;">Failed to generate AI diagnosis framework: ${error.message || error}</span>`;
|
|
351
262
|
}
|
|
352
263
|
}
|
|
353
|
-
async function
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
264
|
+
async function generateNlpToTsScenario(promptText) {
|
|
265
|
+
const apiKey = process.env.GEMINI_API_KEY;
|
|
266
|
+
if (!apiKey) {
|
|
267
|
+
console.warn("\u26A0\uFE0F GEMINI_API_KEY missing. Falling back to default transactional scenario.");
|
|
268
|
+
return getDefaultTransactionalScenario();
|
|
357
269
|
}
|
|
358
|
-
|
|
270
|
+
console.log(`\u{1F916} [NLP Scenario Generator]: Translating natural language prompt into TS simulation scenario via Gemini 2.5 Flash...`);
|
|
271
|
+
console.log(`Prompt: "${promptText}"`);
|
|
272
|
+
const systemPrompt = `
|
|
273
|
+
You are an expert Performance & Load Testing Architect. Your task is to convert the following natural language description of a user journey into a strict JSON array of HTTP transaction steps for a TypeScript load testing script.
|
|
274
|
+
|
|
275
|
+
Each step in the array must be an object with the following fields:
|
|
276
|
+
- "name": string (descriptive name of the step)
|
|
277
|
+
- "url": string (target URL, supporting dynamic token interpolation like \${token_name})
|
|
278
|
+
- "method": string ("GET", "POST", "PUT", "DELETE", etc.)
|
|
279
|
+
- "headers": object (optional key-value pairs of HTTP headers, e.g. { "Authorization": "Bearer \${auth_token}", "Content-Type": "application/json" })
|
|
280
|
+
- "body": string or null (stringified JSON or payload, supporting dynamic tokens)
|
|
281
|
+
- "extractors": object (optional key-value pairs to extract dynamic tokens from response headers/body)
|
|
282
|
+
|
|
283
|
+
Natural Language Journey Description:
|
|
284
|
+
"${promptText}"
|
|
285
|
+
|
|
286
|
+
CRITICAL REQUIREMENTS:
|
|
287
|
+
1. Return ONLY a valid JSON array. No markdown code blocks, no preamble, no explanatory text.
|
|
288
|
+
2. Ensure proper handling of headers, dynamic tokens, and multi-step transaction loops.
|
|
289
|
+
3. If the prompt implies multiple iterations or steps, sequence them logically in the array.
|
|
290
|
+
`;
|
|
291
|
+
try {
|
|
292
|
+
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=${apiKey}`, {
|
|
293
|
+
method: "POST",
|
|
294
|
+
headers: { "Content-Type": "application/json" },
|
|
295
|
+
body: JSON.stringify({
|
|
296
|
+
contents: [{ parts: [{ text: systemPrompt }] }],
|
|
297
|
+
generationConfig: {
|
|
298
|
+
temperature: 0.1,
|
|
299
|
+
maxOutputTokens: 8192
|
|
300
|
+
}
|
|
301
|
+
})
|
|
302
|
+
});
|
|
303
|
+
const data = await response.json();
|
|
304
|
+
if (data?.error) {
|
|
305
|
+
throw new Error(`Google API Error ${data.error.code}: ${data.error.message}`);
|
|
306
|
+
}
|
|
307
|
+
const candidateText = data?.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
308
|
+
if (!candidateText) {
|
|
309
|
+
throw new Error("Empty response body from Gemini API.");
|
|
310
|
+
}
|
|
311
|
+
const cleanedJson = candidateText.replace(/```json/g, "").replace(/```/g, "").trim();
|
|
312
|
+
const parsedScenario = JSON.parse(cleanedJson);
|
|
313
|
+
if (!Array.isArray(parsedScenario) || parsedScenario.length === 0) {
|
|
314
|
+
throw new Error("Generated scenario is not a valid non-empty array.");
|
|
315
|
+
}
|
|
316
|
+
console.log(`\u2705 Successfully generated ${parsedScenario.length} transaction steps from natural language.`);
|
|
317
|
+
return parsedScenario;
|
|
318
|
+
} catch (error) {
|
|
319
|
+
console.error(`\u274C NLP Scenario Generation failed: ${error.message || error}. Falling back to default scenario.`);
|
|
320
|
+
return getDefaultTransactionalScenario();
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
function getDefaultTransactionalScenario() {
|
|
324
|
+
return [
|
|
359
325
|
{
|
|
360
326
|
name: "Fetch Target Anti-Forgery Nonce",
|
|
361
327
|
url: "https://httpbin.org/json",
|
|
362
328
|
method: "GET",
|
|
329
|
+
headers: { "Accept": "application/json" },
|
|
363
330
|
body: null
|
|
364
331
|
},
|
|
365
332
|
{
|
|
366
333
|
name: "Perform Contextual Post Action",
|
|
367
334
|
url: "https://httpbin.org/post?verification=${csrf_token}",
|
|
368
335
|
method: "POST",
|
|
336
|
+
headers: { "Content-Type": "application/json", "Authorization": "Bearer ${bearer_token}" },
|
|
369
337
|
body: JSON.stringify({
|
|
370
338
|
data: "performance_payload",
|
|
371
339
|
security_token: "${csrf_token}"
|
|
372
340
|
})
|
|
373
341
|
}
|
|
374
342
|
];
|
|
343
|
+
}
|
|
344
|
+
async function executeTestPipeline(config) {
|
|
345
|
+
if (!blazeCore || typeof blazeCore.runCorrelatedTransaction !== "function") {
|
|
346
|
+
console.error("\u274C Error: runCorrelatedTransaction function is missing from the compiled binary bindings.");
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
let transactionalScenario;
|
|
350
|
+
if (config.nlpPrompt) {
|
|
351
|
+
transactionalScenario = await generateNlpToTsScenario(config.nlpPrompt);
|
|
352
|
+
} else if (config.targetScript && fs.existsSync(config.targetScript) && !fs.lstatSync(config.targetScript).isDirectory()) {
|
|
353
|
+
const fileContent = fs.readFileSync(config.targetScript, "utf-8");
|
|
354
|
+
if (fileContent.length < 1e3 && !fileContent.includes("import ")) {
|
|
355
|
+
transactionalScenario = await generateNlpToTsScenario(fileContent);
|
|
356
|
+
} else {
|
|
357
|
+
transactionalScenario = getDefaultTransactionalScenario();
|
|
358
|
+
}
|
|
359
|
+
} else {
|
|
360
|
+
transactionalScenario = getDefaultTransactionalScenario();
|
|
361
|
+
}
|
|
375
362
|
console.log(`Launching automated script transaction analysis for: ${config.targetScript}`);
|
|
376
363
|
const sanitizedSteps = transactionalScenario.map((step) => ({
|
|
377
364
|
...step,
|
|
365
|
+
headers: step.headers || { "Content-Type": "application/json" },
|
|
378
366
|
body: typeof step.body === "string" ? step.body : step.body ? JSON.stringify(step.body) : ""
|
|
379
367
|
}));
|
|
380
368
|
const success = await blazeCore.runCorrelatedTransaction(sanitizedSteps);
|
|
@@ -389,10 +377,7 @@ async function main() {
|
|
|
389
377
|
return;
|
|
390
378
|
}
|
|
391
379
|
const config = parseArguments(args);
|
|
392
|
-
if (config.
|
|
393
|
-
await handleScenarioGeneration(config);
|
|
394
|
-
}
|
|
395
|
-
if (config.isCorrelate) {
|
|
380
|
+
if (config.isCorrelate || config.nlpPrompt) {
|
|
396
381
|
await executeTestPipeline(config);
|
|
397
382
|
}
|
|
398
383
|
if (config.isAgentic) {
|
|
@@ -402,17 +387,16 @@ async function main() {
|
|
|
402
387
|
}
|
|
403
388
|
}
|
|
404
389
|
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
390
|
const targetScript = path.resolve(args[0] || ".");
|
|
412
391
|
const isAgentic = args.includes("--agentic");
|
|
413
392
|
const isCorrelate = args.includes("--correlate");
|
|
414
393
|
const isSeo = args.includes("--seo");
|
|
415
394
|
const clusterLogs = !args.includes("--no-cluster-logs");
|
|
395
|
+
let nlpPrompt = null;
|
|
396
|
+
const promptIdx = args.indexOf("--prompt");
|
|
397
|
+
if (promptIdx !== -1) nlpPrompt = args[promptIdx + 1];
|
|
398
|
+
const nlpScenarioIdx = args.indexOf("--nlp-scenario");
|
|
399
|
+
if (nlpScenarioIdx !== -1) nlpPrompt = args[nlpScenarioIdx + 1];
|
|
416
400
|
let threads = 10;
|
|
417
401
|
let durationSec = 10;
|
|
418
402
|
let rampUpSec = 0;
|
|
@@ -461,11 +445,11 @@ function parseArguments(args) {
|
|
|
461
445
|
}
|
|
462
446
|
return {
|
|
463
447
|
targetScript,
|
|
464
|
-
scenarioPrompt,
|
|
465
448
|
isAgentic,
|
|
466
449
|
isCorrelate,
|
|
467
450
|
isSeo,
|
|
468
451
|
clusterLogs,
|
|
452
|
+
nlpPrompt,
|
|
469
453
|
threads,
|
|
470
454
|
durationSec,
|
|
471
455
|
rampUpSec,
|
|
@@ -914,10 +898,10 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
914
898
|
<table style="width: 100%; border-collapse: collapse;">
|
|
915
899
|
<thead>
|
|
916
900
|
<tr style="border-bottom: 1px solid #1e293b;">
|
|
917
|
-
<th style="width: 8%; padding: 0.75rem; text-align: left; color: #64748b; font-size: 0.85rem; font-weight: bold;
|
|
918
|
-
<th style="width: 22%; padding: 0.75rem; text-align: left; color: #64748b; font-size: 0.85rem; font-weight: bold;
|
|
919
|
-
<th style="width: 10%; padding: 0.75rem; text-align: left; color: #64748b; font-size: 0.85rem; font-weight: bold;
|
|
920
|
-
<th style="width: 60%; padding: 0.75rem; text-align: left; color: #64748b; font-size: 0.85rem; font-weight: bold;
|
|
901
|
+
<th style="width: 8%; padding: 0.75rem; text-align: left; color: #64748b; font-size: 0.85rem; font-weight: bold;">Count</th>
|
|
902
|
+
<th style="width: 22%; padding: 0.75rem; text-align: left; color: #64748b; font-size: 0.85rem; font-weight: bold;">Classification Category</th>
|
|
903
|
+
<th style="width: 10%; padding: 0.75rem; text-align: left; color: #64748b; font-size: 0.85rem; font-weight: bold;">Severity</th>
|
|
904
|
+
<th style="width: 60%; padding: 0.75rem; text-align: left; color: #64748b; font-size: 0.85rem; font-weight: bold;">Structural Abstract Blueprint / Dynamic Log Fingerprint</th>
|
|
921
905
|
</tr>
|
|
922
906
|
</thead>
|
|
923
907
|
<tbody>
|
|
@@ -1037,12 +1021,12 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
1037
1021
|
<div style="display: flex; gap: 0.75rem; margin-bottom: 0.75rem;">
|
|
1038
1022
|
<input type="text" id="nlpQueryInput" placeholder="e.g., show me tiers where latency > 40ms or error rate > 0%"
|
|
1039
1023
|
style="flex: 1; background: #090d16; border: 1px solid #1e293b; border-radius: 6px; padding: 0.75rem 1rem; color: #ffffff; font-size: 0.95rem; outline: none; transition: border-color 0.2s;">
|
|
1040
|
-
<button id="nlpQueryBtn" style="background: #0ea5e9; color: #ffffff; border: none; border-radius: 6px; padding: 0.75rem 1.5rem; font-weight: 600; cursor: pointer;
|
|
1024
|
+
<button id="nlpQueryBtn" style="background: #0ea5e9; color: #ffffff; border: none; border-radius: 6px; padding: 0.75rem 1.5rem; font-weight: 600; cursor: pointer;">
|
|
1041
1025
|
Query Matrix
|
|
1042
1026
|
</button>
|
|
1043
1027
|
</div>
|
|
1044
1028
|
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center;">
|
|
1045
|
-
<span style="font-size: 0.8rem; color: #64748b; font-weight: bold; text-transform: uppercase;
|
|
1029
|
+
<span style="font-size: 0.8rem; color: #64748b; font-weight: bold; text-transform: uppercase;">Suggestions:</span>
|
|
1046
1030
|
<button onclick="setNlpQuery('Show P95 latency > 50ms')" style="background: #1e293b; color: #cbd5e1; border: 1px solid #334155; border-radius: 4px; padding: 0.25rem 0.5rem; font-size: 0.8rem; cursor: pointer;">P95 Latency > 50ms</button>
|
|
1047
1031
|
<button onclick="setNlpQuery('Find tiers with errors > 0%')" style="background: #1e293b; color: #cbd5e1; border: 1px solid #334155; border-radius: 4px; padding: 0.25rem 0.5rem; font-size: 0.8rem; cursor: pointer;">Errors > 0%</button>
|
|
1048
1032
|
<button onclick="setNlpQuery('High concurrency > 25 VUs')" style="background: #1e293b; color: #cbd5e1; border: 1px solid #334155; border-radius: 4px; padding: 0.25rem 0.5rem; font-size: 0.8rem; cursor: pointer;">Concurrency > 25 VUs</button>
|
|
@@ -1062,11 +1046,10 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
1062
1046
|
`;
|
|
1063
1047
|
}).join("");
|
|
1064
1048
|
const gaugeColor = cards.healthScore >= 90 ? "#10b981" : cards.healthScore >= 70 ? "#f59e0b" : "#ef4444";
|
|
1065
|
-
const chartJsCdn = "https://cdn.jsdelivr.net/npm/chart.js";
|
|
1066
1049
|
const htmlContent = `<!DOCTYPE html><html lang="en"><head>
|
|
1067
1050
|
<meta charset="UTF-8">
|
|
1068
1051
|
<title>Blaze Core Performance Report</title>
|
|
1069
|
-
<script src="
|
|
1052
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
1070
1053
|
<style>
|
|
1071
1054
|
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0b111e; color: #f8fafc; margin: 0; padding: 2rem; }
|
|
1072
1055
|
.container { max-width: 1300px; margin: 0 auto; }
|
|
@@ -1122,7 +1105,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
1122
1105
|
</style></head><body>
|
|
1123
1106
|
<div class="container">
|
|
1124
1107
|
<div class="header">
|
|
1125
|
-
<h1>\u{1F525} Blaze Core Performance
|
|
1108
|
+
<h1>\u{1F525} Blaze Core Performance Analysis</h1>
|
|
1126
1109
|
<div class="meta">Target Script: <code>${config.targetScript}</code> | Ramp-Up: ${config.rampUpSec}s | Ramp-Down: ${config.rampDownSec}s</div>
|
|
1127
1110
|
</div>
|
|
1128
1111
|
|
|
@@ -1323,7 +1306,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
1323
1306
|
const feedback = document.getElementById('nlpQueryFeedback');
|
|
1324
1307
|
|
|
1325
1308
|
let filterFn = (row, data) => true;
|
|
1326
|
-
const numMatch = q.match(/(
|
|
1309
|
+
const numMatch = q.match(/(d+(?:.d+)?)/);
|
|
1327
1310
|
const targetNum = numMatch ? parseFloat(numMatch[1]) : null;
|
|
1328
1311
|
|
|
1329
1312
|
const isGreater = q.includes('>') || q.includes('greater') || q.includes('above') || q.includes('more');
|
|
@@ -1559,14 +1542,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
|
|
|
1559
1542
|
function printUsage() {
|
|
1560
1543
|
console.log(`Blaze Core Performance Test CLI Engine
|
|
1561
1544
|
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`);
|
|
1545
|
+
--threads <count> | --duration <seconds> | --baseline <json_file> | --output <html_file> | --prompt "<natural language description>" | --correlate`);
|
|
1571
1546
|
}
|
|
1572
1547
|
main().catch(console.error);
|
|
Binary file
|