blaze-performance-tester 3.1.60 → 3.1.61

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/bin.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import './dist/cli.js';
package/dist/cli.js CHANGED
@@ -1,9 +1,6 @@
1
- #!/usr/bin/env node
2
- #!/usr/bin/env node
1
+ #!/usr/bin/env ts-node
3
2
 
4
3
  // cli.ts
5
- import { Command } from "commander";
6
- import chalk from "chalk";
7
4
  import { createRequire } from "module";
8
5
  import * as path from "path";
9
6
  import { fileURLToPath } from "url";
@@ -137,7 +134,8 @@ var blazeCore;
137
134
  try {
138
135
  blazeCore = require2(nativeBindingPath);
139
136
  } catch (e) {
140
- console.error(chalk.red(`\u274C Failed to load native C++ bindings from ${nativeBindingPath}`));
137
+ console.error(`\u274C Failed to load native C++ bindings from ${nativeBindingPath}`);
138
+ process.exit(1);
141
139
  }
142
140
  var mathUtils = {
143
141
  mean: (arr) => arr.length === 0 ? 0 : arr.reduce((p, c) => p + c, 0) / arr.length,
@@ -153,46 +151,6 @@ var mathUtils = {
153
151
  return sorted[Math.max(0, index)];
154
152
  }
155
153
  };
156
- function getMockRegionalData() {
157
- return [
158
- { zone: "us-east-1", location: "N. Virginia", latencyAvg: 24, p99: 68, errorRate: 0.02, status: "optimal" },
159
- { zone: "eu-central-1", location: "Frankfurt", latencyAvg: 42, p99: 115, errorRate: 0.14, status: "stable" },
160
- { zone: "ap-south-1", location: "Mumbai", latencyAvg: 88, p99: 210, errorRate: 0.85, status: "elevated" },
161
- { zone: "ap-northeast-1", location: "Tokyo", latencyAvg: 55, p99: 130, errorRate: 0.05, status: "stable" },
162
- { zone: "sa-east-1", location: "S\xE3o Paulo", latencyAvg: 112, p99: 285, errorRate: 1.2, status: "critical" }
163
- ];
164
- }
165
- function renderStatusBadge(status) {
166
- switch (status) {
167
- case "optimal":
168
- return chalk.green("\u{1F7E2} OPTIMAL");
169
- case "stable":
170
- return chalk.green("\u{1F7E2} STABLE");
171
- case "elevated":
172
- return chalk.yellow("\u{1F7E1} ELEVATED");
173
- case "critical":
174
- return chalk.red("\u{1F534} CRITICAL");
175
- default:
176
- return chalk.gray("\u26AA UNKNOWN");
177
- }
178
- }
179
- function renderGeographicHeatmap(regions) {
180
- console.log(chalk.bold.cyan("\n============================================================"));
181
- console.log(chalk.bold.cyan(" BLAZE: GEOGRAPHIC LATENCY HEATMAP & MATRIX "));
182
- console.log(chalk.bold.cyan("============================================================\n"));
183
- console.log(
184
- `${chalk.bold("Zone".padEnd(16))} | ${chalk.bold("Location".padEnd(14))} | ${chalk.bold("Avg (ms)".padEnd(10))} | ${chalk.bold("P99 (ms)".padEnd(10))} | ${chalk.bold("Error Rate".padEnd(12))} | ${chalk.bold("Status")}`
185
- );
186
- console.log("-".repeat(78));
187
- for (const r of regions) {
188
- const errorColor = r.errorRate > 1 ? chalk.red : r.errorRate > 0.5 ? chalk.yellow : chalk.green;
189
- const latencyColor = r.latencyAvg > 100 ? chalk.yellow : chalk.white;
190
- console.log(
191
- `${r.zone.padEnd(16)} | ${r.location.padEnd(14)} | ${latencyColor(String(r.latencyAvg).padEnd(10))} | ${String(r.p99).padEnd(10)} | ${errorColor(`${r.errorRate.toFixed(2)}%`).padEnd(20)} | ${renderStatusBadge(r.status)}`
192
- );
193
- }
194
- console.log("\n");
195
- }
196
154
  function getLoadMultiplier(elapsedMs, rampUpMs, steadyMs, rampDownMs) {
197
155
  const totalDurationMs = rampUpMs + steadyMs + rampDownMs;
198
156
  if (elapsedMs < rampUpMs && rampUpMs > 0) {
@@ -210,64 +168,20 @@ function loadBaselineData(filePath) {
210
168
  try {
211
169
  const resolved = path.resolve(filePath);
212
170
  if (fs.existsSync(resolved)) {
213
- console.log(chalk.blue(`\u{1F4C1} Loaded baseline comparison telemetry from: ${resolved}`));
171
+ console.log(`\u{1F4C1} Loaded baseline comparison telemetry from: ${resolved}`);
214
172
  return JSON.parse(fs.readFileSync(resolved, "utf-8"));
215
173
  }
216
174
  } catch (e) {
217
- console.error(chalk.red(`\u274C Failed to parse baseline telemetry file: ${e}`));
175
+ console.error(`\u274C Failed to parse baseline telemetry file: ${e}`);
218
176
  }
219
177
  return null;
220
178
  }
221
- function calculateSeoImpactMetrics(avgLatencyMs) {
222
- const baseLineOptimalMs = 200;
223
- if (avgLatencyMs <= baseLineOptimalMs) {
224
- return { trafficLoss: 0, status: "Excellent", crawlPenalty: "None", color: "#10b981" };
225
- }
226
- const delayFactor = avgLatencyMs - baseLineOptimalMs;
227
- const trafficLoss = Math.min(94, Math.floor(delayFactor / 1200 * 100));
228
- let status = "Healthy";
229
- let crawlPenalty = "Minimal impact on indexing rates.";
230
- let color = "#10b981";
231
- if (trafficLoss >= 50) {
232
- status = "Critical Exposure";
233
- crawlPenalty = "Severe penalty. Googlebot will heavily restrict crawl budgets due to timeout risks.";
234
- color = "#ef4444";
235
- } else if (trafficLoss >= 20) {
236
- status = "Moderate Danger";
237
- crawlPenalty = "Delayed indexation. Core Web Vital thresholds are officially breached.";
238
- color = "#f97316";
239
- } else if (trafficLoss > 5) {
240
- status = "Minor Impact";
241
- crawlPenalty = "Slightly elevated bounce trends could impact highly volatile rankings.";
242
- color = "#eab308";
243
- }
244
- return { trafficLoss, status, crawlPenalty, color };
245
- }
246
- function computeHealthScoreValue(apdex, errorRate, p95Latency, maxAllowedLatency) {
247
- const apdexComponent = apdex * 50;
248
- const errorComponent = Math.max(0, 1 - errorRate) * 30;
249
- const latencyRatio = p95Latency / maxAllowedLatency;
250
- const latencyComponent = Math.max(0, 1 - Math.min(1, latencyRatio)) * 20;
251
- return Math.min(100, Math.max(0, Math.round(apdexComponent + errorComponent + latencyComponent)));
252
- }
253
- function getFallbackClusterLogs() {
254
- const logs = [];
255
- const add = (msg, count) => {
256
- for (let i = 0; i < count; i++) logs.push(`[2026-07-08T12:08:18.000Z] ${msg}`);
257
- };
258
- add("JsonWebTokenError: jwt expired at JMT.verify (\\app\\node_modules\\jsonwebtoken\\index.js:5)", 37);
259
- add("Error: ECONNREFUSED 127.0.0.1:5432 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1)", 33);
260
- add("TypeError: Cannot read properties of undefined (reading 'config_id') at Object.execute (\\app\\dist\\handler.js:42:19)", 31);
261
- add("HTTP/1.1 504 Gateway Timeout on POST /api/v1/checkout - upstream socket drop after 15000ms", 25);
262
- add("HTTP/1.1 504 Gateway Timeout on POST /api/v1/checkout - upstream socket drop after 30000ms", 19);
263
- return logs;
264
- }
265
179
  async function generateGeminiRCA(history, finalSummary, errorLogs) {
266
180
  const apiKey = process.env.GEMINI_API_KEY;
267
181
  if (!apiKey) {
268
182
  return `<span style="color: #ef4444;">\u26A0\uFE0F Gemini API Key missing. Export GEMINI_API_KEY to enable automated 2.5 Flash RCA analysis.</span>`;
269
183
  }
270
- console.log(chalk.magenta("\u{1F9E0} Querying Gemini 2.5 Flash for Advanced Root Cause Analysis..."));
184
+ console.log("\u{1F9E0} Querying Gemini 2.5 Flash for Advanced Root Cause Analysis...");
271
185
  const formattedHistory = history.map(
272
186
  (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)}`
273
187
  ).join("\n");
@@ -323,97 +237,127 @@ CRITICAL: Return ONLY plain paragraph text. Do not use markdown headers (###). I
323
237
  }
324
238
  return candidateText.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>").replace(/\n/g, "<br>");
325
239
  } catch (error) {
326
- console.error(chalk.red("\u274C Gemini API processing breakdown failure:"), error);
240
+ console.error("\u274C Gemini API processing breakdown failure:", error);
327
241
  return `<span style="color: #f87171;">Failed to generate AI diagnosis framework: ${error.message || error}</span>`;
328
242
  }
329
243
  }
330
- function generateSimulationData(threads, durationSec, maxAllowedLatencyMs, rampUpSec = 0, rampDownSec = 0) {
331
- const data = [];
332
- const totalRequests = Math.max(15, threads * durationSec * 30);
333
- const startTime = Date.now();
334
- const rampUpMs = rampUpSec * 1e3;
335
- const steadyMs = durationSec * 1e3;
336
- const rampDownMs = rampDownSec * 1e3;
337
- const totalTestMs = rampUpMs + steadyMs + rampDownMs;
338
- const targetThresholdBreak = Math.max(5, Math.floor(maxAllowedLatencyMs * 0.05));
339
- const errorPool = getFallbackClusterLogs();
340
- for (let i = 0; i < totalRequests; i++) {
341
- const offsetMs = Math.random() * totalTestMs;
342
- const loadFactor = getLoadMultiplier(offsetMs, rampUpMs, steadyMs, rampDownMs);
343
- if (loadFactor <= 0) continue;
344
- const effectiveThreads = Math.max(1, threads * loadFactor);
345
- const isBreached = effectiveThreads > targetThresholdBreak;
346
- const stressFactor = isBreached ? Math.pow(effectiveThreads / targetThresholdBreak, 1.5) : 1;
347
- const isError = Math.random() < (isBreached ? 0.05 : 1e-3);
348
- const baseLatency = (25 + Math.random() * 35) * stressFactor;
349
- let errorMessage;
350
- let statusCode = 200;
351
- if (isError) {
352
- const targetResponseCodes = [400, 401, 403, 404, 429, 500, 502, 503, 504];
353
- statusCode = targetResponseCodes[Math.floor(Math.random() * targetResponseCodes.length)];
354
- errorMessage = errorPool[Math.floor(Math.random() * errorPool.length)];
244
+ async function executeTestPipeline(config) {
245
+ if (!blazeCore || typeof blazeCore.runCorrelatedTransaction !== "function") {
246
+ console.error("\u274C Error: runCorrelatedTransaction function is missing from the compiled binary bindings.");
247
+ return;
248
+ }
249
+ const transactionalScenario = [
250
+ {
251
+ name: "Fetch Target Anti-Forgery Nonce",
252
+ url: "https://httpbin.org/json",
253
+ method: "GET",
254
+ body: null
255
+ },
256
+ {
257
+ name: "Perform Contextual Post Action",
258
+ url: "https://httpbin.org/post?verification=${csrf_token}",
259
+ method: "POST",
260
+ body: JSON.stringify({
261
+ data: "performance_payload",
262
+ security_token: "${csrf_token}"
263
+ })
355
264
  }
356
- data.push({
357
- durationMs: isError ? baseLatency * 0.1 : baseLatency,
358
- timestampMs: startTime + offsetMs,
359
- dnsTimeMs: 1 + Math.random() * 0.9,
360
- tcpTimeMs: 4 + Math.random() * 1.5,
361
- tlsTimeMs: 6 + Math.random() * 1.8,
362
- statusCode,
363
- errorMessage
364
- });
265
+ ];
266
+ console.log(`Launching automated script transaction analysis for: ${config.targetScript}`);
267
+ const sanitizedSteps = transactionalScenario.map((step) => ({
268
+ ...step,
269
+ body: typeof step.body === "string" ? step.body : step.body ? JSON.stringify(step.body) : ""
270
+ }));
271
+ const success = await blazeCore.runCorrelatedTransaction(sanitizedSteps);
272
+ if (success) {
273
+ console.log("Pipeline run complete. Parameter tracking successfully mitigated breaking changes.");
365
274
  }
366
- return data.sort((a, b) => a.timestampMs - b.timestampMs);
367
275
  }
368
- function processMetricsTelemetry(requests, durationSec) {
369
- const totalRequests = requests.length;
370
- const durations = requests.map((r) => r.durationMs);
371
- const avgLatencyMs = mathUtils.mean(durations);
372
- const stdDevMs = mathUtils.stdDev(durations, avgLatencyMs);
373
- const p95LatencyMs = mathUtils.percentile(durations, 95);
374
- const avgDnsMs = mathUtils.mean(requests.map((r) => r.dnsTimeMs || 0));
375
- const avgTcpMs = mathUtils.mean(requests.map((r) => r.tcpTimeMs || 0));
376
- const avgTlsMs = mathUtils.mean(requests.map((r) => r.tlsTimeMs || 0));
377
- const avgTtfbMs = avgDnsMs + avgTcpMs + avgTlsMs + avgLatencyMs * 0.3;
378
- let c1xx = 0, c2xx = 0, c3xx = 0, c4xx = 0, c5xx = 0;
379
- const codeCounts = { 400: 0, 401: 0, 403: 0, 404: 0, 429: 0, 500: 0, 502: 0, 503: 0, 504: 0 };
380
- [400, 401, 403, 404, 429, 500, 502, 503, 504].forEach((c) => codeCounts[c] = 0);
381
- requests.forEach((r) => {
382
- if (r.statusCode >= 100 && r.statusCode < 200) c1xx++;
383
- else if (r.statusCode >= 200 && r.statusCode < 300) c2xx++;
384
- else if (r.statusCode >= 300 && r.statusCode < 400) c3xx++;
385
- else if (r.statusCode >= 400 && r.statusCode < 500) c4xx++;
386
- else if (r.statusCode >= 500) c5xx++;
387
- if (r.statusCode in codeCounts) {
388
- codeCounts[r.statusCode]++;
276
+ async function main() {
277
+ const args = process.argv.slice(2);
278
+ if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
279
+ printUsage();
280
+ return;
281
+ }
282
+ const config = parseArguments(args);
283
+ if (config.isCorrelate) {
284
+ await executeTestPipeline(config);
285
+ }
286
+ if (config.isAgentic) {
287
+ await runIntelligentAgenticStressTest(config);
288
+ } else {
289
+ await runStandardStressTest(config);
290
+ }
291
+ }
292
+ function parseArguments(args) {
293
+ const targetScript = path.resolve(args[0] || ".");
294
+ const isAgentic = args.includes("--agentic");
295
+ const isCorrelate = args.includes("--correlate");
296
+ const isSeo = args.includes("--seo");
297
+ const clusterLogs = !args.includes("--no-cluster-logs");
298
+ let threads = 10;
299
+ let durationSec = 10;
300
+ let rampUpSec = 0;
301
+ let rampDownSec = 0;
302
+ let targetApdex = 0.85;
303
+ let targetErrorRate = 0.01;
304
+ let maxThreads = 300;
305
+ let maxAllowedLatencyMs = 800;
306
+ let outputHtml = "blaze-dashboard.html";
307
+ let baselinePath = null;
308
+ const threadsIdx = args.indexOf("--threads");
309
+ if (threadsIdx !== -1) threads = parseInt(args[threadsIdx + 1], 10);
310
+ const durationIdx = args.indexOf("--duration");
311
+ if (durationIdx !== -1) durationSec = parseInt(args[durationIdx + 1], 10);
312
+ const rampUpIdx = args.indexOf("--ramp-up");
313
+ if (rampUpIdx !== -1) rampUpSec = parseInt(args[rampUpIdx + 1], 10);
314
+ const rampDownIdx = args.indexOf("--ramp-down");
315
+ if (rampDownIdx !== -1) rampDownSec = parseInt(args[rampDownIdx + 1], 10);
316
+ const apdexIdx = args.indexOf("--target-apdex");
317
+ if (apdexIdx !== -1) targetApdex = parseFloat(apdexIdx + 1);
318
+ const errorIdx = args.indexOf("--target-error");
319
+ if (errorIdx !== -1) targetErrorRate = parseFloat(args[errorIdx + 1]);
320
+ const maxThreadsIdx = args.indexOf("--max-threads");
321
+ if (maxThreadsIdx !== -1) maxThreads = parseInt(args[maxThreadsIdx + 1], 10);
322
+ const outputIdx = args.indexOf("--output");
323
+ if (outputIdx !== -1) outputHtml = args[outputIdx + 1];
324
+ const baselineIdx = args.indexOf("--baseline");
325
+ if (baselineIdx !== -1) baselinePath = args[baselineIdx + 1];
326
+ const positionalNums = args.slice(1).filter((arg) => !arg.startsWith("-")).map(Number).filter((n) => !isNaN(n));
327
+ if (positionalNums.length > 0 && threadsIdx === -1 && !isAgentic) threads = positionalNums[0];
328
+ if (positionalNums.length > 1 && durationIdx === -1 && !isAgentic) durationSec = positionalNums[1];
329
+ if (positionalNums.length > 2 && errorIdx === -1 && !isAgentic) targetErrorRate = positionalNums[2] / 100;
330
+ if (isAgentic) {
331
+ const agenticIdx = args.indexOf("--agentic");
332
+ const trailingArgs = args.slice(agenticIdx + 1).filter((arg) => !arg.startsWith("--"));
333
+ if (trailingArgs[0]) maxThreads = parseInt(trailingArgs[0], 10);
334
+ if (trailingArgs[1]) {
335
+ let rawLatency = parseFloat(trailingArgs[1]);
336
+ if (rawLatency < 50) {
337
+ maxAllowedLatencyMs = rawLatency * 1e3;
338
+ } else {
339
+ maxAllowedLatencyMs = rawLatency;
340
+ }
389
341
  }
390
- });
391
- const errorCount = c4xx + c5xx;
392
- const errorRate = totalRequests === 0 ? 0 : errorCount / totalRequests;
393
- const T = 50;
394
- const satisfied = requests.filter((r) => r.durationMs <= T && r.statusCode < 400).length;
395
- const tolerating = requests.filter((r) => r.durationMs > T && r.durationMs <= T * 4 && r.statusCode < 400).length;
396
- const apdexScore = totalRequests === 0 ? 0 : (satisfied + tolerating / 2) / totalRequests;
397
- const bandwidthMb = totalRequests * 1.2 / durationSec / 10;
342
+ if (trailingArgs[2]) targetErrorRate = parseFloat(trailingArgs[2]) / 100;
343
+ }
398
344
  return {
399
- totalRequests,
400
- requestsPerSecond: totalRequests / durationSec,
401
- avgLatencyMs,
402
- stdDevMs,
403
- p95LatencyMs,
404
- errorRate,
405
- apdexScore,
406
- c1xx,
407
- c2xx,
408
- c3xx,
409
- c4xx,
410
- c5xx,
411
- avgDnsMs,
412
- avgTcpMs,
413
- avgTlsMs,
414
- avgTtfbMs,
415
- bandwidthMb,
416
- codeCounts
345
+ targetScript,
346
+ isAgentic,
347
+ isCorrelate,
348
+ isSeo,
349
+ clusterLogs,
350
+ threads,
351
+ durationSec,
352
+ rampUpSec,
353
+ rampDownSec,
354
+ targetApdex,
355
+ targetErrorRate,
356
+ maxThreads,
357
+ stepSize: 15,
358
+ maxAllowedLatencyMs,
359
+ outputHtml,
360
+ baselinePath
417
361
  };
418
362
  }
419
363
  async function runBlazeCoreEngine(config) {
@@ -437,62 +381,40 @@ async function runBlazeCoreEngine(config) {
437
381
  }, 1e3);
438
382
  });
439
383
  }
440
- function printMatrixDashboard(m, threads) {
441
- const pad = (val, size) => String(val).padEnd(size).substring(0, size);
442
- console.log(`-----------------------------------------------------------------------------------------`);
443
- console.log(`| Threads | Samples | Avg Latency | P95 Latency | Throughput | Error Rate | Apdex |`);
444
- console.log(`-----------------------------------------------------------------------------------------`);
445
- console.log(`| ${pad(threads, 7)} | ${pad(m.totalRequests, 9)} | ${pad(m.avgLatencyMs.toFixed(1) + "ms", 11)} | ${pad(m.p95LatencyMs.toFixed(1) + "ms", 11)} | ${pad(m.requestsPerSecond.toFixed(0) + "/s", 10)} | ${pad((m.errorRate * 100).toFixed(2) + "%", 10)} | ${pad(m.apdexScore.toFixed(2), 9)} |`);
446
- console.log(`-----------------------------------------------------------------------------------------`);
447
- }
448
- function generateFinalAgentReport(history, score) {
449
- if (history.length === 0) return;
450
- const peakThroughput = Math.max(...history.map((h) => h.throughput));
451
- const cleanRuns = history.filter((h) => h.apdex >= 0.85 && h.errorRate <= 0.01);
452
- const maxSafeThreads = cleanRuns.length > 0 ? cleanRuns[cleanRuns.length - 1].threads : history[0].threads;
453
- console.log(chalk.bold.green("\n======================================================="));
454
- console.log(chalk.bold.cyan("\u{1F9E0} INTELLIGENT AUTONOMOUS LOAD AGENT FINAL REPORT"));
455
- console.log(chalk.bold.green("======================================================="));
456
- console.log(`\u{1F7E2} Unified Blaze Health Score : ${score}/100`);
457
- console.log(`\u{1F3C6} Recommended Max Safe Concurrency : ${maxSafeThreads} allocation threads`);
458
- console.log(`\u{1F4A5} Infrastructure Failure Boundary : ${history[history.length - 1].threads} concurrency allocation`);
459
- console.log(`\u26A1 Peak Achieved Cluster Velocity : ${peakThroughput.toFixed(0)} req/sec`);
460
- console.log(chalk.bold.green("=======================================================\n"));
461
- }
462
- async function executeTestPipeline(config) {
463
- if (!blazeCore || typeof blazeCore.runCorrelatedTransaction !== "function") {
464
- console.error(chalk.red("\u274C Error: runCorrelatedTransaction function is missing from the compiled binary bindings."));
465
- return;
384
+ function calculateSeoImpactMetrics(avgLatencyMs) {
385
+ const baseLineOptimalMs = 200;
386
+ if (avgLatencyMs <= baseLineOptimalMs) {
387
+ return { trafficLoss: 0, status: "Excellent", crawlPenalty: "None", color: "#10b981" };
466
388
  }
467
- const transactionalScenario = [
468
- {
469
- name: "Fetch Target Anti-Forgery Nonce",
470
- url: "https://httpbin.org/json",
471
- method: "GET",
472
- body: null
473
- },
474
- {
475
- name: "Perform Contextual Post Action",
476
- url: "https://httpbin.org/post?verification=${csrf_token}",
477
- method: "POST",
478
- body: JSON.stringify({
479
- data: "performance_payload",
480
- security_token: "${csrf_token}"
481
- })
482
- }
483
- ];
484
- console.log(chalk.blue(`Launching automated script transaction analysis for: ${config.targetScript}`));
485
- const sanitizedSteps = transactionalScenario.map((step) => ({
486
- ...step,
487
- body: typeof step.body === "string" ? step.body : step.body ? JSON.stringify(step.body) : ""
488
- }));
489
- const success = await blazeCore.runCorrelatedTransaction(sanitizedSteps);
490
- if (success) {
491
- console.log(chalk.green("Pipeline run complete. Parameter tracking successfully mitigated breaking changes."));
389
+ const delayFactor = avgLatencyMs - baseLineOptimalMs;
390
+ const trafficLoss = Math.min(94, Math.floor(delayFactor / 1200 * 100));
391
+ let status = "Healthy";
392
+ let crawlPenalty = "Minimal impact on indexing rates.";
393
+ let color = "#10b981";
394
+ if (trafficLoss >= 50) {
395
+ status = "Critical Exposure";
396
+ crawlPenalty = "Severe penalty. Googlebot will heavily restrict crawl budgets due to timeout risks.";
397
+ color = "#ef4444";
398
+ } else if (trafficLoss >= 20) {
399
+ status = "Moderate Danger";
400
+ crawlPenalty = "Delayed indexation. Core Web Vital thresholds are officially breached.";
401
+ color = "#f97316";
402
+ } else if (trafficLoss > 5) {
403
+ status = "Minor Impact";
404
+ crawlPenalty = "Slightly elevated bounce trends could impact highly volatile rankings.";
405
+ color = "#eab308";
492
406
  }
407
+ return { trafficLoss, status, crawlPenalty, color };
408
+ }
409
+ function computeHealthScoreValue(apdex, errorRate, p95Latency, maxAllowedLatency) {
410
+ const apdexComponent = apdex * 50;
411
+ const errorComponent = Math.max(0, 1 - errorRate) * 30;
412
+ const latencyRatio = p95Latency / maxAllowedLatency;
413
+ const latencyComponent = Math.max(0, 1 - Math.min(1, latencyRatio)) * 20;
414
+ return Math.min(100, Math.max(0, Math.round(apdexComponent + errorComponent + latencyComponent)));
493
415
  }
494
416
  async function runIntelligentAgenticStressTest(config) {
495
- console.log(chalk.magenta("\u{1F680} Initializing Intelligent Autonomous Load Agent..."));
417
+ console.log("\u{1F680} Initializing Intelligent Autonomous Load Agent...");
496
418
  const history = [];
497
419
  let aggregateErrorLogs = [];
498
420
  let lastRawRequests = [];
@@ -506,7 +428,7 @@ async function runIntelligentAgenticStressTest(config) {
506
428
  let verdictReason = "The system successfully scaled and remained stable within parameters up to maximum configured capacity allocations.";
507
429
  let saturationKneePoint = null;
508
430
  while (currentThreads <= config.maxThreads && isStable) {
509
- console.log(chalk.yellow(`\u{1F916} [Agent Decision]: Testing execution tier at ${currentThreads} concurrent threads...`));
431
+ console.log(`\u{1F916} [Agent Decision]: Testing execution tier at ${currentThreads} concurrent threads...`);
510
432
  const { metrics, rawErrors, rawRequests } = await runBlazeCoreEngine({ ...config, threads: currentThreads });
511
433
  if (config.clusterLogs) {
512
434
  aggregateErrorLogs = aggregateErrorLogs.concat(rawErrors);
@@ -599,7 +521,7 @@ async function runIntelligentAgenticStressTest(config) {
599
521
  if (config.isSeo) {
600
522
  const finalLat = finalState.avgLatency || finalSummaryCards.ttfb;
601
523
  const seo = calculateSeoImpactMetrics(finalLat);
602
- console.log(chalk.bold.yellow(`\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}].`));
524
+ 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}].`);
603
525
  }
604
526
  const breakdownRates = {};
605
527
  Object.keys(globalCodeCounts).forEach((codeStr) => {
@@ -610,11 +532,11 @@ async function runIntelligentAgenticStressTest(config) {
610
532
  exportHtmlDashboard(history, config, verdictReason, semanticReport, { total1xx, total2xx, total3xx, total4xx, total5xx, breakdownRates }, finalSummaryCards, lastRawRequests, geminiAnalysisHtml, baselineData);
611
533
  }
612
534
  async function runStandardStressTest(config) {
613
- console.log(chalk.blue(`\u{1F3CB}\uFE0F Running Standard Stress Test [Threads: ${config.threads} | Duration: ${config.durationSec}s | RampUp: ${config.rampUpSec}s | RampDown: ${config.rampDownSec}s]`));
535
+ console.log(`\u{1F3CB}\uFE0F Running Standard Stress Test [Threads: ${config.threads} | Duration: ${config.durationSec}s | RampUp: ${config.rampUpSec}s | RampDown: ${config.rampDownSec}s]`);
614
536
  const { metrics, rawErrors, rawRequests } = await runBlazeCoreEngine(config);
615
537
  printMatrixDashboard(metrics, config.threads);
616
538
  const healthScore = computeHealthScoreValue(metrics.apdexScore, metrics.errorRate, metrics.p95LatencyMs, config.maxAllowedLatencyMs);
617
- console.log(chalk.green(`\u{1F49A} Unified Blaze Health Score: ${healthScore}/100`));
539
+ console.log(`\u{1F49A} Unified Blaze Health Score: ${healthScore}/100`);
618
540
  const history = [{
619
541
  threads: config.threads,
620
542
  avgLatency: metrics.avgLatencyMs,
@@ -651,7 +573,7 @@ async function runStandardStressTest(config) {
651
573
  const geminiAnalysisHtml = await generateGeminiRCA(history, finalSummaryCards, rawErrors.length > 0 ? rawErrors : getFallbackClusterLogs());
652
574
  if (config.isSeo) {
653
575
  const seo = calculateSeoImpactMetrics(metrics.avgLatencyMs);
654
- console.log(chalk.bold.yellow(`\u{1F50E} [SEO Impact Report]: Target latency (${metrics.avgLatencyMs.toFixed(1)}ms) triggers a predicted Search Visibility Loss of -${seo.trafficLoss}% [Status: ${seo.status}].`));
576
+ 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}].`);
655
577
  }
656
578
  const breakdownRates = {};
657
579
  Object.keys(metrics.codeCounts).forEach((codeStr) => {
@@ -668,6 +590,129 @@ async function runStandardStressTest(config) {
668
590
  breakdownRates
669
591
  }, finalSummaryCards, rawRequests, geminiAnalysisHtml, baselineData);
670
592
  }
593
+ function getFallbackClusterLogs() {
594
+ const logs = [];
595
+ const add = (msg, count) => {
596
+ for (let i = 0; i < count; i++) logs.push(`[2026-07-08T12:08:18.000Z] ${msg}`);
597
+ };
598
+ add("JsonWebTokenError: jwt expired at JMT.verify (\\app\\node_modules\\jsonwebtoken\\index.js:5)", 37);
599
+ add("Error: ECONNREFUSED 127.0.0.1:5432 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1)", 33);
600
+ add("TypeError: Cannot read properties of undefined (reading 'config_id') at Object.execute (\\app\\dist\\handler.js:42:19)", 31);
601
+ add("HTTP/1.1 504 Gateway Timeout on POST /api/v1/checkout - upstream socket drop after 15000ms", 25);
602
+ add("HTTP/1.1 504 Gateway Timeout on POST /api/v1/checkout - upstream socket drop after 30000ms", 19);
603
+ return logs;
604
+ }
605
+ function generateSimulationData(threads, durationSec, maxAllowedLatencyMs, rampUpSec = 0, rampDownSec = 0) {
606
+ const data = [];
607
+ const totalRequests = Math.max(15, threads * durationSec * 30);
608
+ const startTime = Date.now();
609
+ const rampUpMs = rampUpSec * 1e3;
610
+ const steadyMs = durationSec * 1e3;
611
+ const rampDownMs = rampDownSec * 1e3;
612
+ const totalTestMs = rampUpMs + steadyMs + rampDownMs;
613
+ const targetThresholdBreak = Math.max(5, Math.floor(maxAllowedLatencyMs * 0.05));
614
+ const errorPool = getFallbackClusterLogs();
615
+ for (let i = 0; i < totalRequests; i++) {
616
+ const offsetMs = Math.random() * totalTestMs;
617
+ const loadFactor = getLoadMultiplier(offsetMs, rampUpMs, steadyMs, rampDownMs);
618
+ if (loadFactor <= 0) continue;
619
+ const effectiveThreads = Math.max(1, threads * loadFactor);
620
+ const isBreached = effectiveThreads > targetThresholdBreak;
621
+ const stressFactor = isBreached ? Math.pow(effectiveThreads / targetThresholdBreak, 1.5) : 1;
622
+ const isError = Math.random() < (isBreached ? 0.05 : 1e-3);
623
+ const baseLatency = (25 + Math.random() * 35) * stressFactor;
624
+ let errorMessage;
625
+ let statusCode = 200;
626
+ if (isError) {
627
+ const targetResponseCodes = [400, 401, 403, 404, 429, 500, 502, 503, 504];
628
+ statusCode = targetResponseCodes[Math.floor(Math.random() * targetResponseCodes.length)];
629
+ errorMessage = errorPool[Math.floor(Math.random() * errorPool.length)];
630
+ }
631
+ data.push({
632
+ durationMs: isError ? baseLatency * 0.1 : baseLatency,
633
+ timestampMs: startTime + offsetMs,
634
+ dnsTimeMs: 1 + Math.random() * 0.9,
635
+ tcpTimeMs: 4 + Math.random() * 1.5,
636
+ tlsTimeMs: 6 + Math.random() * 1.8,
637
+ statusCode,
638
+ errorMessage
639
+ });
640
+ }
641
+ return data.sort((a, b) => a.timestampMs - b.timestampMs);
642
+ }
643
+ function processMetricsTelemetry(requests, durationSec) {
644
+ const totalRequests = requests.length;
645
+ const durations = requests.map((r) => r.durationMs);
646
+ const avgLatencyMs = mathUtils.mean(durations);
647
+ const stdDevMs = mathUtils.stdDev(durations, avgLatencyMs);
648
+ const p95LatencyMs = mathUtils.percentile(durations, 95);
649
+ const avgDnsMs = mathUtils.mean(requests.map((r) => r.dnsTimeMs || 0));
650
+ const avgTcpMs = mathUtils.mean(requests.map((r) => r.tcpTimeMs || 0));
651
+ const avgTlsMs = mathUtils.mean(requests.map((r) => r.tlsTimeMs || 0));
652
+ const avgTtfbMs = avgDnsMs + avgTcpMs + avgTlsMs + avgLatencyMs * 0.3;
653
+ let c1xx = 0, c2xx = 0, c3xx = 0, c4xx = 0, c5xx = 0;
654
+ const codeCounts = { 400: 0, 401: 0, 403: 0, 404: 0, 429: 0, 500: 0, 502: 0, 503: 0, 504: 0 };
655
+ [400, 401, 403, 404, 429, 500, 502, 503, 504].forEach((c) => codeCounts[c] = 0);
656
+ requests.forEach((r) => {
657
+ if (r.statusCode >= 100 && r.statusCode < 200) c1xx++;
658
+ else if (r.statusCode >= 200 && r.statusCode < 300) c2xx++;
659
+ else if (r.statusCode >= 300 && r.statusCode < 400) c3xx++;
660
+ else if (r.statusCode >= 400 && r.statusCode < 500) c4xx++;
661
+ else if (r.statusCode >= 500) c5xx++;
662
+ if (r.statusCode in codeCounts) {
663
+ codeCounts[r.statusCode]++;
664
+ }
665
+ });
666
+ const errorCount = c4xx + c5xx;
667
+ const errorRate = totalRequests === 0 ? 0 : errorCount / totalRequests;
668
+ const T = 50;
669
+ const satisfied = requests.filter((r) => r.durationMs <= T && r.statusCode < 400).length;
670
+ const tolerating = requests.filter((r) => r.durationMs > T && r.durationMs <= T * 4 && r.statusCode < 400).length;
671
+ const apdexScore = totalRequests === 0 ? 0 : (satisfied + tolerating / 2) / totalRequests;
672
+ const bandwidthMb = totalRequests * 1.2 / durationSec / 10;
673
+ return {
674
+ totalRequests,
675
+ requestsPerSecond: totalRequests / durationSec,
676
+ avgLatencyMs,
677
+ stdDevMs,
678
+ p95LatencyMs,
679
+ errorRate,
680
+ apdexScore,
681
+ c1xx,
682
+ c2xx,
683
+ c3xx,
684
+ c4xx,
685
+ c5xx,
686
+ avgDnsMs,
687
+ avgTcpMs,
688
+ avgTlsMs,
689
+ avgTtfbMs,
690
+ bandwidthMb,
691
+ codeCounts
692
+ };
693
+ }
694
+ function printMatrixDashboard(m, threads) {
695
+ const pad = (val, size) => String(val).padEnd(size).substring(0, size);
696
+ console.log(`-----------------------------------------------------------------------------------------`);
697
+ console.log(`| Threads | Samples | Avg Latency | P95 Latency | Throughput | Error Rate | Apdex |`);
698
+ console.log(`-----------------------------------------------------------------------------------------`);
699
+ console.log(`| ${pad(threads, 7)} | ${pad(m.totalRequests, 9)} | ${pad(m.avgLatencyMs.toFixed(1) + "ms", 11)} | ${pad(m.p95LatencyMs.toFixed(1) + "ms", 11)} | ${pad(m.requestsPerSecond.toFixed(0) + "/s", 10)} | ${pad((m.errorRate * 100).toFixed(2) + "%", 10)} | ${pad(m.apdexScore.toFixed(2), 9)} |`);
700
+ console.log(`-----------------------------------------------------------------------------------------`);
701
+ }
702
+ function generateFinalAgentReport(history, score) {
703
+ if (history.length === 0) return;
704
+ const peakThroughput = Math.max(...history.map((h) => h.throughput));
705
+ const cleanRuns = history.filter((h) => h.apdex >= 0.85 && h.errorRate <= 0.01);
706
+ const maxSafeThreads = cleanRuns.length > 0 ? cleanRuns[cleanRuns.length - 1].threads : history[0].threads;
707
+ console.log("\n=======================================================");
708
+ console.log("\u{1F9E0} INTELLIGENT AUTONOMOUS LOAD AGENT FINAL REPORT");
709
+ console.log("=======================================================");
710
+ console.log(`\u{1F49A} Unified Blaze Health Score : ${score}/100`);
711
+ console.log(`\u{1F3C6} Recommended Max Safe Concurrency : ${maxSafeThreads} allocation threads`);
712
+ console.log(`\u{1F4A5} Infrastructure Failure Boundary : ${history[history.length - 1].threads} concurrency allocation`);
713
+ console.log(`\u26A1 Peak Achieved Cluster Velocity : ${peakThroughput.toFixed(0)} req/sec`);
714
+ console.log("=======================================================\n");
715
+ }
671
716
  function exportHtmlDashboard(history, config, verdictReason, semanticReport, responseMatrix, cards, rawRequests = [], geminiAnalysisHtml = "", baselineData = null) {
672
717
  const summaryArtifactPath = config.outputHtml.replace(/\.html$/, "-summary.json");
673
718
  try {
@@ -1158,7 +1203,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1158
1203
  const feedback = document.getElementById('nlpQueryFeedback');
1159
1204
 
1160
1205
  let filterFn = (row, data) => true;
1161
- const numMatch = q.match(/(\\d+(?:\\.\\d+)?)/);
1206
+ const numMatch = q.match(/(d+(?:.d+)?)/);
1162
1207
  const targetNum = numMatch ? parseFloat(numMatch[1]) : null;
1163
1208
 
1164
1209
  const isGreater = q.includes('>') || q.includes('greater') || q.includes('above') || q.includes('more');
@@ -1386,69 +1431,14 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1386
1431
  </script></body></html>`;
1387
1432
  try {
1388
1433
  fs.writeFileSync(config.outputHtml, htmlContent, "utf-8");
1389
- console.log(chalk.bold.green(`\u{1F4CA} Standalone Dashboard exported successfully to: ${path.resolve(config.outputHtml)}`));
1434
+ console.log(`\u{1F4CA} Standalone Dashboard exported successfully to: ${path.resolve(config.outputHtml)}`);
1390
1435
  } catch (err) {
1391
- console.error(chalk.red(`\u274C Failed to write HTML output dashboard: ${err}`));
1436
+ console.error(`\u274C Failed to write HTML output dashboard: ${err}`);
1392
1437
  }
1393
1438
  }
1394
- var program = new Command();
1395
- program.name("blaze").description("Blaze CLI - High-performance distributed load and latency tester").version("1.0.0");
1396
- program.command("run").description("Run a distributed load or local performance/stress test pipeline").argument("[script]", "Target script or directory path to evaluate", ".").option("-u, --url <url>", "Target simulation URL for distributed load routing", "https://api.example.com/health").option("-r, --regions <zones>", "Comma-separated list of target AWS/Cloud zones to simulate (e.g. us-east-1,eu-central-1,ap-south-1)").option("-t, --threads <threads>", "Number of parallel virtual users (VUs)", "10").option("-d, --duration <seconds>", "Test duration in seconds", "10").option("--ramp-up <seconds>", "Ramp-up duration in seconds", "0").option("--ramp-down <seconds>", "Ramp-down duration in seconds", "0").option("--target-apdex <score>", "Target Apdex satisfaction index (0.0 to 1.0)", "0.85").option("--target-error <rate>", "Target maximum allowed error rate (e.g. 0.01 for 1%)", "0.01").option("--max-threads <max>", "Maximum parallel threads for dynamic agentic scaling tests", "300").option("--max-allowed-latency <ms>", "SLA violation latency threshold (in milliseconds)", "800").option("-o, --output <filename>", "Destination path of the exported interactive HTML telemetry dashboard", "blaze-dashboard.html").option("--baseline <filepath>", "Reference JSON summary data to run automatic regression comparisons").option("--agentic", "Deploy the autonomous cognitive agent to auto-scale load until failure limits are hit", false).option("--correlate", "Enable transaction tracking pipelines (mitigates CSRF/nonce state mutations)", false).option("--seo", "Model SEO bounce rate, googlebot budget indexing penalties, and visibility impact", false).option("--no-cluster-logs", "Disable structural failure pattern clustering").action(async (script, options) => {
1397
- const parsedThreads = parseInt(options.threads, 10);
1398
- const parsedDuration = parseInt(options.duration, 10);
1399
- const parsedRampUp = parseInt(options.rampUp, 10) || 0;
1400
- const parsedRampDown = parseInt(options.rampDown, 10) || 0;
1401
- const parsedApdex = parseFloat(options.targetApdex);
1402
- const parsedError = parseFloat(options.targetError);
1403
- const parsedMaxThreads = parseInt(options.maxThreads, 10);
1404
- const parsedMaxLatencyRaw = parseFloat(options.maxAllowedLatency || "800");
1405
- const parsedMaxLatency = parsedMaxLatencyRaw < 50 ? parsedMaxLatencyRaw * 1e3 : parsedMaxLatencyRaw;
1406
- const config = {
1407
- targetScript: path.resolve(script || "."),
1408
- isAgentic: !!options.agentic,
1409
- isCorrelate: !!options.correlate,
1410
- isSeo: !!options.seo,
1411
- clusterLogs: options.clusterLogs !== false,
1412
- threads: parsedThreads,
1413
- durationSec: parsedDuration,
1414
- rampUpSec: parsedRampUp,
1415
- rampDownSec: parsedRampDown,
1416
- targetApdex: parsedApdex,
1417
- targetErrorRate: parsedError,
1418
- maxThreads: parsedMaxThreads,
1419
- stepSize: 15,
1420
- maxAllowedLatencyMs: parsedMaxLatency,
1421
- outputHtml: options.output,
1422
- baselinePath: options.baseline || null
1423
- };
1424
- if (options.regions) {
1425
- console.log(chalk.blue(`
1426
- Initializing Blaze load test simulation against ${chalk.bold(options.url)}...`));
1427
- console.log(chalk.gray(`Target regions: ${options.regions}`));
1428
- console.log(chalk.gray(`Duration: ${options.duration}s
1429
- `));
1430
- await new Promise((resolve2) => {
1431
- setTimeout(() => {
1432
- const allRegions = getMockRegionalData();
1433
- const requestedZones = options.regions.split(",").map((z) => z.trim());
1434
- const filteredRegions = allRegions.filter((r) => requestedZones.includes(r.zone));
1435
- renderGeographicHeatmap(filteredRegions.length > 0 ? filteredRegions : allRegions);
1436
- console.log(chalk.gray(`Executing localized system stress verification pipelines...
1437
- `));
1438
- resolve2(null);
1439
- }, 1e3);
1440
- });
1441
- }
1442
- if (config.isCorrelate) {
1443
- await executeTestPipeline(config);
1444
- }
1445
- if (config.isAgentic) {
1446
- await runIntelligentAgenticStressTest(config);
1447
- } else {
1448
- await runStandardStressTest(config);
1449
- }
1450
- });
1451
- program.command("heatmap").description("Display real-time geographic latency heatmap breakdown").action(() => {
1452
- renderGeographicHeatmap(getMockRegionalData());
1453
- });
1454
- program.parse(process.argv);
1439
+ function printUsage() {
1440
+ console.log(`Blaze Core Performance Test CLI Engine
1441
+ Options:
1442
+ --threads <count> | --duration <seconds> | --baseline <json_file> | --output <html_file>`);
1443
+ }
1444
+ 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.60",
3
+ "version": "3.1.61",
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",
@@ -8,7 +8,7 @@
8
8
  "author": "Kushan Shalindra Amarsiri <lkkushan@yahoo.com>",
9
9
  "license": "MIT",
10
10
  "bin": {
11
- "blaze": "./dist/cli.js"
11
+ "blaze": "./bin.js"
12
12
  },
13
13
  "files": [
14
14
  "dist",
@@ -18,18 +18,16 @@
18
18
  "blaze.win32-x64-msvc.node"
19
19
  ],
20
20
  "scripts": {
21
- "prebuild": "node -e \"const fs = require('fs'); if (!fs.existsSync('dist')) fs.mkdirSync('dist')\"",
21
+ "prebuild": "node -e \"if (!fs.existsSync('dist')) fs.mkdirSync('dist')\"",
22
22
  "build:rust": "napi build --platform --release --output-dir dist --js index.js --dts index.d.ts",
23
- "build:cli": "esbuild cli.ts --bundle --platform=node --format=esm --packages=external --banner:js=\"#!/usr/bin/env node\" --outfile=dist/cli.js",
23
+ "build:cli": "esbuild cli.ts --bundle --platform=node --format=esm --packages=external --outfile=dist/cli.js",
24
24
  "build": "npm run prebuild && npm run build:rust && npm run build:cli"
25
25
  },
26
26
  "dependencies": {
27
- "chalk": "^5.3.0",
28
- "commander": "^12.1.0"
27
+ "esbuild": "^0.20.0"
29
28
  },
30
29
  "devDependencies": {
31
30
  "@napi-rs/cli": "^2.16.0",
32
- "esbuild": "^0.20.0",
33
31
  "typescript": "^5.0.0"
34
32
  }
35
- }
33
+ }