blaze-performance-tester 3.1.61 → 3.2.0

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
@@ -23,7 +23,13 @@ var LogAnalyzer = class {
23
23
  return { category: "Environment_Infrastructure_Error", severity: "CRITICAL" };
24
24
  }
25
25
  if (LowercaseTpl.includes("401") || LowercaseTpl.includes("403") || LowercaseTpl.includes("unauthorized") || LowercaseTpl.includes("forbidden") || LowercaseTpl.includes("jwt") || LowercaseTpl.includes("token expired")) {
26
- return { category: "Authentication_Error", severity: "CRITICAL" };
26
+ return { category: "Authentication_Error", severity: "HIGH" };
27
+ }
28
+ if (LowercaseTpl.includes("429") || LowercaseTpl.includes("rate limit") || LowercaseTpl.includes("too many requests")) {
29
+ return { category: "Traffic_Management_Error", severity: "MEDIUM" };
30
+ }
31
+ if (LowercaseTpl.includes("typeerror") || LowercaseTpl.includes("undefined") || LowercaseTpl.includes("nullpointer") || LowercaseTpl.includes("cannot read properties")) {
32
+ return { category: "Product_Error", severity: "CRITICAL" };
27
33
  }
28
34
  return { category: "Product_Error", severity: "WARNING" };
29
35
  }
@@ -31,16 +37,17 @@ var LogAnalyzer = class {
31
37
  * Generates actionable architectural and code-level fixes based on log structural fingerprints
32
38
  */
33
39
  generatePlaybook(template, severity) {
34
- if (severity !== "CRITICAL" && severity !== "HIGH") {
40
+ if (severity !== "CRITICAL" && severity !== "HIGH" && severity !== "MEDIUM") {
35
41
  return void 0;
36
42
  }
43
+ const lowerTemplate = template.toLowerCase();
37
44
  if (template.includes("ECONNREFUSED") || template.includes("5432")) {
38
45
  return `**Database Connectivity Failure**
39
46
  1. **Service Triage:** Verify the target PostgreSQL instance at 127.0.0.1:5432 is running using \`pg_isready\`.
40
47
  2. **Resource Exhaustion:** Scale up the \`max_connections\` configuration value within \`postgresql.conf\`.
41
48
  3. **Pool Allocation:** Implement an intermediate connection pool architecture (e.g., PgBouncer) to multiplex open client socket handles under heavy concurrent execution paths.`;
42
49
  }
43
- if (template.includes("504 Gateway Timeout") || template.includes("upstream socket drop")) {
50
+ if (template.includes("504 Gateway Timeout") || template.includes("upstream socket drop") || template.includes("Timeout")) {
44
51
  return `**Upstream Gateway Timeout Saturation**
45
52
  1. **Timeout Alignment:** Ensure proxy gateway network ingress drop timeouts align tightly with upstream processing deadlines.
46
53
  2. **Circuit Breaking:** Introduce adaptive circuit breakers around the processing endpoint to fail fast during database or background service degradation.
@@ -58,10 +65,19 @@ var LogAnalyzer = class {
58
65
  2. **Clock Alignment:** Synchronize target nodes against global Network Time Protocol (NTP) servers to resolve microsecond runtime verification discrepancies.
59
66
  3. **Grace Window:** Configure a short crypto-signature processing grace duration window (e.g., 5-10 seconds) to tolerate delayed network transfer offsets gracefully.`;
60
67
  }
61
- return `**High-Severity System Anomaly Action Plan**
68
+ if (lowerTemplate.includes("429") || lowerTemplate.includes("rate limit") || lowerTemplate.includes("too many requests")) {
69
+ return `**Traffic Rate Limit Triggered**
70
+ 1. **Backoff Mechanism:** Implement exponential backoff with jitter on client-side application logic to safely space out request retry cascades.
71
+ 2. **Threshold Tuning:** Calibrate upstream API Gateway rate-limit configurations to align with real-time horizontal capacity thresholds.
72
+ 3. **Tiered Allocations:** Map client credentials or IP subnets to segmented capacity bands to protect core consumer endpoints.`;
73
+ }
74
+ if (severity === "CRITICAL" || severity === "HIGH") {
75
+ return `**High-Severity System Anomaly Action Plan**
62
76
  1. **Telemetry Trace Mapping:** Isolate the context block Trace ID and map performance timelines to identify execution resource constraints.
63
77
  2. **Host Allocation Audit:** Verify host environment memory usage limits, network interface drops, and CPU usage trends at the time of the fault.
64
78
  3. **Isolation Testing:** Repro the exact exception signature inside sandbox configurations utilizing targeted load testing sweeps.`;
79
+ }
80
+ return void 0;
65
81
  }
66
82
  /**
67
83
  * Processes a stream of raw textual error logs into deduplicated clustered fingerprints
@@ -86,12 +102,16 @@ var LogAnalyzer = class {
86
102
  template = "Error: ECONNREFUSED 127.0.0.1:5432 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1)";
87
103
  } else if (cleanLog.includes("TypeError") || cleanLog.includes("Cannot read properties")) {
88
104
  category = "Product_Error";
89
- severity = "HIGH";
105
+ severity = "CRITICAL";
90
106
  template = "TypeError: Cannot read properties of undefined (reading 'config_id') at Object.execute (\\app\\dist\\handler.js:42:19)";
91
- } else if (cleanLog.includes("504 Gateway Timeout")) {
107
+ } else if (cleanLog.includes("504 Gateway Timeout") || cleanLog.includes("upstream socket drop")) {
92
108
  category = "Environment_Infrastructure_Error";
93
109
  severity = "CRITICAL";
94
110
  template = cleanLog.includes("15000ms") ? "HTTP/1.1 504 Gateway Timeout on POST /api/v1/checkout - upstream socket drop after 15000ms" : "HTTP/1.1 504 Gateway Timeout on POST /api/v1/checkout - upstream socket drop after 30000ms";
111
+ } else if (cleanLog.includes("429") || /rate limit|too many requests/i.test(cleanLog)) {
112
+ category = "Traffic_Management_Error";
113
+ severity = "MEDIUM";
114
+ template = "HTTP/1.1 429 Too Many Requests - Rate limit exceeded";
95
115
  }
96
116
  if (!template) {
97
117
  template = this.extractLogTemplate(log);
@@ -176,6 +196,93 @@ function loadBaselineData(filePath) {
176
196
  }
177
197
  return null;
178
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 response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=${apiKey}`, {
229
+ method: "POST",
230
+ headers: { "Content-Type": "application/json" },
231
+ body: JSON.stringify({
232
+ contents: [{ parts: [{ text: `Generate a Virtual User script for this scenario: ${prompt}` }] }],
233
+ generationConfig: {
234
+ temperature: 0.1,
235
+ maxOutputTokens: 65536
236
+ },
237
+ systemInstruction: {
238
+ parts: [{ text: systemInstruction }]
239
+ }
240
+ })
241
+ });
242
+ const data = await response.json();
243
+ if (data?.error) {
244
+ throw new Error(`Google API Error ${data.error.code}: ${data.error.message}`);
245
+ }
246
+ const candidateText = data?.candidates?.[0]?.content?.parts?.[0]?.text;
247
+ if (!candidateText) {
248
+ throw new Error(`Malformed API layout or empty response body.`);
249
+ }
250
+ return candidateText.replace(/```typescript/g, "").replace(/```javascript/g, "").replace(/```/g, "").trim();
251
+ } catch (error) {
252
+ throw new Error(`Failed to generate script via Gemini: ${error.message || error}`);
253
+ }
254
+ }
255
+ async function handleScenarioGeneration(config) {
256
+ const targetDir = path.resolve(__dirname, "./tests");
257
+ const tsFilePath = path.join(targetDir, "generated_scenario.ts");
258
+ const jsFilePath = path.join(targetDir, "generated_scenario.js");
259
+ try {
260
+ if (!fs.existsSync(targetDir)) {
261
+ fs.mkdirSync(targetDir, { recursive: true });
262
+ }
263
+ const tsCode = await generateScenarioTS(config.scenarioPrompt);
264
+ fs.writeFileSync(tsFilePath, tsCode, "utf-8");
265
+ console.log(`\u{1F4BE} Successfully generated scenario script saved to: ${tsFilePath}`);
266
+ console.log("\u2699\uFE0F Transpiling generated scenario to JavaScript for native QuickJS sandbox validation...");
267
+ let compiledSuccessfully = false;
268
+ try {
269
+ const { execSync } = require2("child_process");
270
+ execSync(`npx tsc "${tsFilePath}" --target es2020 --module commonjs --allowJs --skipLibCheck`, { stdio: "ignore" });
271
+ compiledSuccessfully = true;
272
+ } catch (e) {
273
+ console.warn("\u26A0\uFE0F TypeScript compiler (tsc) was not found or timed out. Falling back to clean JS copy conversion...");
274
+ }
275
+ if (!compiledSuccessfully) {
276
+ const cleanJs = tsCode.replace(/: VirtualUser/g, "").replace(/import {[^}]+} from .*/g, "").replace(/export async/g, "async");
277
+ fs.writeFileSync(jsFilePath, cleanJs, "utf-8");
278
+ }
279
+ console.log(`\u2705 Sandbox compilation resolved. Active test file: ${jsFilePath}`);
280
+ config.targetScript = jsFilePath;
281
+ } catch (error) {
282
+ console.error(`\u274C Scenario generation flow aborted: ${error.message || error}`);
283
+ process.exit(1);
284
+ }
285
+ }
179
286
  async function generateGeminiRCA(history, finalSummary, errorLogs) {
180
287
  const apiKey = process.env.GEMINI_API_KEY;
181
288
  if (!apiKey) {
@@ -212,7 +319,7 @@ Paragraph 3 - ARCHITECTURAL SIZING RECOMMENDATIONS: Give concrete, infrastructur
212
319
  CRITICAL: Return ONLY plain paragraph text. Do not use markdown headers (###). If you use bold text, use standard HTML <strong> tags. Wrap lines cleanly.
213
320
  `;
214
321
  try {
215
- const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=${apiKey}`, {
322
+ const response = await fetch(`[https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=$](https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=$){apiKey}`, {
216
323
  method: "POST",
217
324
  headers: { "Content-Type": "application/json" },
218
325
  body: JSON.stringify({
@@ -249,13 +356,13 @@ async function executeTestPipeline(config) {
249
356
  const transactionalScenario = [
250
357
  {
251
358
  name: "Fetch Target Anti-Forgery Nonce",
252
- url: "https://httpbin.org/json",
359
+ url: "[https://httpbin.org/json](https://httpbin.org/json)",
253
360
  method: "GET",
254
361
  body: null
255
362
  },
256
363
  {
257
364
  name: "Perform Contextual Post Action",
258
- url: "https://httpbin.org/post?verification=${csrf_token}",
365
+ url: "[https://httpbin.org/post?verification=$](https://httpbin.org/post?verification=$){csrf_token}",
259
366
  method: "POST",
260
367
  body: JSON.stringify({
261
368
  data: "performance_payload",
@@ -280,6 +387,9 @@ async function main() {
280
387
  return;
281
388
  }
282
389
  const config = parseArguments(args);
390
+ if (config.scenarioPrompt) {
391
+ await handleScenarioGeneration(config);
392
+ }
283
393
  if (config.isCorrelate) {
284
394
  await executeTestPipeline(config);
285
395
  }
@@ -290,6 +400,12 @@ async function main() {
290
400
  }
291
401
  }
292
402
  function parseArguments(args) {
403
+ const scenarioIdx = args.indexOf("--generate-scenario");
404
+ let scenarioPrompt = null;
405
+ if (scenarioIdx !== -1) {
406
+ scenarioPrompt = args[scenarioIdx + 1];
407
+ args.splice(scenarioIdx, 2);
408
+ }
293
409
  const targetScript = path.resolve(args[0] || ".");
294
410
  const isAgentic = args.includes("--agentic");
295
411
  const isCorrelate = args.includes("--correlate");
@@ -314,7 +430,7 @@ function parseArguments(args) {
314
430
  const rampDownIdx = args.indexOf("--ramp-down");
315
431
  if (rampDownIdx !== -1) rampDownSec = parseInt(args[rampDownIdx + 1], 10);
316
432
  const apdexIdx = args.indexOf("--target-apdex");
317
- if (apdexIdx !== -1) targetApdex = parseFloat(apdexIdx + 1);
433
+ if (apdexIdx !== -1) targetApdex = parseFloat(args[apdexIdx + 1]);
318
434
  const errorIdx = args.indexOf("--target-error");
319
435
  if (errorIdx !== -1) targetErrorRate = parseFloat(args[errorIdx + 1]);
320
436
  const maxThreadsIdx = args.indexOf("--max-threads");
@@ -343,6 +459,7 @@ function parseArguments(args) {
343
459
  }
344
460
  return {
345
461
  targetScript,
462
+ scenarioPrompt,
346
463
  isAgentic,
347
464
  isCorrelate,
348
465
  isSeo,
@@ -937,7 +1054,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
937
1054
  const displayColor = rate > 0 ? code >= 500 ? "#f87171" : "#fde047" : "#64748b";
938
1055
  return `
939
1056
  <div style="background: #090d16; border: 1px solid #1e293b; border-radius: 4px; padding: 0.4rem 0.2rem; text-align: center;">
940
- <div style="font-size: 0.7rem; color: #64748b; font-weight: bold;">${code}</div>
1057
+ <div style="font-size: 0.7rem; color: #64748b; font-weight: bold;">Code ${code}</div>
941
1058
  <div style="font-size: 0.85rem; font-weight: bold; color: ${displayColor};">${rate.toFixed(2)}%</div>
942
1059
  </div>
943
1060
  `;
@@ -946,7 +1063,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
946
1063
  const htmlContent = `<!DOCTYPE html><html lang="en"><head>
947
1064
  <meta charset="UTF-8">
948
1065
  <title>Blaze Core Performance Report</title>
949
- <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
1066
+ <script src="[https://cdn.jsdelivr.net/npm/chart.js](https://cdn.jsdelivr.net/npm/chart.js)"></script>
950
1067
  <style>
951
1068
  body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0b111e; color: #f8fafc; margin: 0; padding: 2rem; }
952
1069
  .container { max-width: 1300px; margin: 0 auto; }
@@ -1203,7 +1320,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1203
1320
  const feedback = document.getElementById('nlpQueryFeedback');
1204
1321
 
1205
1322
  let filterFn = (row, data) => true;
1206
- const numMatch = q.match(/(d+(?:.d+)?)/);
1323
+ const numMatch = q.match(/(\\d+(?:\\.\\d+)?)/);
1207
1324
  const targetNum = numMatch ? parseFloat(numMatch[1]) : null;
1208
1325
 
1209
1326
  const isGreater = q.includes('>') || q.includes('greater') || q.includes('above') || q.includes('more');
@@ -1439,6 +1556,14 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1439
1556
  function printUsage() {
1440
1557
  console.log(`Blaze Core Performance Test CLI Engine
1441
1558
  Options:
1442
- --threads <count> | --duration <seconds> | --baseline <json_file> | --output <html_file>`);
1559
+ --generate-scenario <prompt> Generates a virtual user script from a natural language prompt
1560
+ --threads <count> Number of concurrent threads (default: 10)
1561
+ --duration <seconds> Duration of stress testing in seconds (default: 10)
1562
+ --ramp-up <seconds> Ramp-up speed
1563
+ --ramp-down <seconds> Ramp-down speed
1564
+ --agentic Enable Intelligent Autonomous Agentic Stress Test
1565
+ --correlate Launch dynamic transaction parameter mapping pipeline
1566
+ --baseline <json_file> Input baseline JSON benchmark reference
1567
+ --output <html_file> Target path for exported standalone dashboard`);
1443
1568
  }
1444
1569
  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.61",
3
+ "version": "3.2.0",
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",