blaze-performance-tester 3.0.22 → 3.0.24

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
@@ -74,19 +74,68 @@ try {
74
74
  process.exit(1);
75
75
  }
76
76
  var mathUtils = {
77
+ //[cite: 2]
77
78
  mean: (arr) => arr.length === 0 ? 0 : arr.reduce((p, c) => p + c, 0) / arr.length,
79
+ //[cite: 2]
78
80
  stdDev: (arr, mean) => {
79
81
  if (arr.length === 0) return 0;
80
82
  const r = arr.reduce((p, c) => p + Math.pow(c - mean, 2), 0);
81
83
  return Math.sqrt(r / arr.length);
82
84
  },
85
+ //[cite: 2]
83
86
  percentile: (arr, p) => {
84
87
  if (arr.length === 0) return 0;
85
88
  const sorted = [...arr].sort((a, b) => a - b);
86
89
  const index = Math.ceil(p / 100 * sorted.length) - 1;
87
90
  return sorted[Math.max(0, index)];
88
91
  }
92
+ //[cite: 2]
89
93
  };
94
+ async function executeTestPipeline() {
95
+ if (!blazeCore || typeof blazeCore.runCorrelatedTransaction !== "function") {
96
+ console.error("\u274C Error: runCorrelatedTransaction function is missing from the compiled binary bindings.");
97
+ return;
98
+ }
99
+ const transactionalScenario = [
100
+ //[cite: 1]
101
+ {
102
+ //[cite: 1]
103
+ name: "Fetch Target Anti-Forgery Nonce",
104
+ //[cite: 1]
105
+ url: "https://httpbin.org/json",
106
+ // Returns metadata configurations //[cite: 1]
107
+ method: "GET",
108
+ //[cite: 1]
109
+ body: null
110
+ //[cite: 1]
111
+ },
112
+ //[cite: 1]
113
+ {
114
+ //[cite: 1]
115
+ name: "Perform Contextual Post Action",
116
+ //[cite: 1]
117
+ // The engine automatically detects ${csrf_token} if returned in Step 1 and swaps it seamlessly //[cite: 1]
118
+ url: "https://httpbin.org/post?verification=${csrf_token}",
119
+ //[cite: 1]
120
+ method: "POST",
121
+ //[cite: 1]
122
+ body: JSON.stringify({
123
+ //[cite: 1]
124
+ data: "performance_payload",
125
+ //[cite: 1]
126
+ security_token: "${csrf_token}"
127
+ //[cite: 1]
128
+ })
129
+ //[cite: 1]
130
+ }
131
+ //[cite: 1]
132
+ ];
133
+ console.log("Launching automated script transaction analysis...");
134
+ const success = await blazeCore.runCorrelatedTransaction(transactionalScenario);
135
+ if (success) {
136
+ console.log("Pipeline run complete. Parameter tracking successfully mitigated breaking changes.");
137
+ }
138
+ }
90
139
  async function main() {
91
140
  const args = process.argv.slice(2);
92
141
  if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
@@ -94,7 +143,9 @@ async function main() {
94
143
  return;
95
144
  }
96
145
  const config = parseArguments(args);
97
- if (config.isAgentic) {
146
+ if (config.isCorrelate) {
147
+ await executeTestPipeline();
148
+ } else if (config.isAgentic) {
98
149
  await runIntelligentAgenticStressTest(config);
99
150
  } else {
100
151
  await runStandardStressTest(config);
@@ -103,6 +154,7 @@ async function main() {
103
154
  function parseArguments(args) {
104
155
  const targetScript = path.resolve(args[0] || ".");
105
156
  const isAgentic = args.includes("--agentic");
157
+ const isCorrelate = args.includes("--correlate");
106
158
  const clusterLogs = args.includes("--cluster-logs");
107
159
  let threads = 10;
108
160
  let durationSec = 10;
@@ -138,17 +190,31 @@ function parseArguments(args) {
138
190
  if (trailingArgs[2]) targetErrorRate = parseFloat(trailingArgs[2]) / 100;
139
191
  }
140
192
  return {
193
+ //[cite: 2]
141
194
  targetScript,
195
+ //[cite: 2]
142
196
  isAgentic,
197
+ //[cite: 2]
198
+ isCorrelate,
199
+ //[cite: 2]
143
200
  clusterLogs,
201
+ //[cite: 2]
144
202
  threads,
203
+ //[cite: 2]
145
204
  durationSec,
205
+ //[cite: 2]
146
206
  targetApdex,
207
+ //[cite: 2]
147
208
  targetErrorRate,
209
+ //[cite: 2]
148
210
  maxThreads,
211
+ //[cite: 2]
149
212
  stepSize: 15,
213
+ //[cite: 2]
150
214
  maxAllowedLatencyMs,
215
+ //[cite: 2]
151
216
  outputHtml
217
+ //[cite: 2]
152
218
  };
153
219
  }
154
220
  async function runBlazeCoreEngine(config) {
@@ -197,14 +263,23 @@ async function runIntelligentAgenticStressTest(config) {
197
263
  globalMetricsAccumulator.latencies.push(metrics.avgLatencyMs);
198
264
  globalMetricsAccumulator.bandwidths.push(metrics.bandwidthMb);
199
265
  const currentState = {
266
+ //[cite: 2]
200
267
  threads: currentThreads,
268
+ //[cite: 2]
201
269
  avgLatency: metrics.avgLatencyMs,
270
+ //[cite: 2]
202
271
  p95Latency: metrics.p95LatencyMs,
272
+ //[cite: 2]
203
273
  errorRate: metrics.errorRate,
274
+ //[cite: 2]
204
275
  apdex: metrics.apdexScore,
276
+ //[cite: 2]
205
277
  throughput: metrics.requestsPerSecond,
278
+ //[cite: 2]
206
279
  successRequests: metrics.c2xx + metrics.c3xx,
280
+ //[cite: 2]
207
281
  failedRequests: metrics.c4xx + metrics.c5xx
282
+ //[cite: 2]
208
283
  };
209
284
  printMatrixDashboard(metrics, currentThreads);
210
285
  history.push(currentState);
@@ -243,14 +318,23 @@ async function runIntelligentAgenticStressTest(config) {
243
318
  semanticReport = analyzer.process(aggregateErrorLogs);
244
319
  }
245
320
  const finalSummaryCards = {
321
+ //[cite: 2]
246
322
  apdex: history[history.length - 1]?.apdex || 0,
323
+ //[cite: 2]
247
324
  throughput: history[history.length - 1]?.throughput || 0,
325
+ //[cite: 2]
248
326
  bandwidth: mathUtils.mean(globalMetricsAccumulator.bandwidths),
327
+ //[cite: 2]
249
328
  ttfb: mathUtils.mean(globalMetricsAccumulator.ttfb),
329
+ //[cite: 2]
250
330
  dns: mathUtils.mean(globalMetricsAccumulator.dns),
331
+ //[cite: 2]
251
332
  tcp: mathUtils.mean(globalMetricsAccumulator.tcp),
333
+ //[cite: 2]
252
334
  tls: mathUtils.mean(globalMetricsAccumulator.tls),
335
+ //[cite: 2]
253
336
  stdDev: mathUtils.stdDev(globalMetricsAccumulator.latencies, mathUtils.mean(globalMetricsAccumulator.latencies))
337
+ //[cite: 2]
254
338
  };
255
339
  generateFinalAgentReport(history);
256
340
  exportHtmlDashboard(history, config, verdictReason, semanticReport, { total2xx, total3xx, total4xx, total5xx }, finalSummaryCards);
@@ -260,14 +344,23 @@ async function runStandardStressTest(config) {
260
344
  const { metrics, rawErrors } = await runBlazeCoreEngine(config);
261
345
  printMatrixDashboard(metrics, config.threads);
262
346
  const history = [{
347
+ //[cite: 2]
263
348
  threads: config.threads,
349
+ //[cite: 2]
264
350
  avgLatency: metrics.avgLatencyMs,
351
+ //[cite: 2]
265
352
  p95Latency: metrics.p95LatencyMs,
353
+ //[cite: 2]
266
354
  errorRate: metrics.errorRate,
355
+ //[cite: 2]
267
356
  apdex: metrics.apdexScore,
357
+ //[cite: 2]
268
358
  throughput: metrics.requestsPerSecond,
359
+ //[cite: 2]
269
360
  successRequests: metrics.c2xx + metrics.c3xx,
361
+ //[cite: 2]
270
362
  failedRequests: metrics.c4xx + metrics.c5xx
363
+ //[cite: 2]
271
364
  }];
272
365
  let semanticReport = null;
273
366
  if (config.clusterLogs && rawErrors.length > 0) {
@@ -275,22 +368,33 @@ async function runStandardStressTest(config) {
275
368
  semanticReport = analyzer.process(rawErrors);
276
369
  }
277
370
  const finalSummaryCards = {
371
+ //[cite: 2]
278
372
  apdex: metrics.apdexScore,
373
+ //[cite: 2]
279
374
  throughput: metrics.requestsPerSecond,
375
+ //[cite: 2]
280
376
  bandwidth: metrics.bandwidthMb,
377
+ //[cite: 2]
281
378
  ttfb: metrics.avgTtfbMs,
379
+ //[cite: 2]
282
380
  dns: metrics.avgDnsMs,
381
+ //[cite: 2]
283
382
  tcp: metrics.avgTcpMs,
383
+ //[cite: 2]
284
384
  tls: metrics.avgTlsMs,
385
+ //[cite: 2]
285
386
  stdDev: metrics.stdDevMs
387
+ //[cite: 2]
286
388
  };
287
389
  const isPassed = metrics.apdexScore >= config.targetApdex && metrics.errorRate <= config.targetErrorRate;
288
390
  const verdictReason = isPassed ? "Static single-wave baseline checks concluded successfully without triggering health boundaries." : "Static verification loop completed with values exceeding defined quality thresholds.";
289
391
  exportHtmlDashboard(history, config, verdictReason, semanticReport, {
392
+ //[cite: 2]
290
393
  total2xx: metrics.c2xx,
291
394
  total3xx: metrics.c3xx,
292
395
  total4xx: metrics.c4xx,
293
396
  total5xx: metrics.c5xx
397
+ //[cite: 2]
294
398
  }, finalSummaryCards);
295
399
  }
296
400
  function generateSimulationData(threads, durationSec, maxAllowedLatencyMs) {
@@ -301,9 +405,13 @@ function generateSimulationData(threads, durationSec, maxAllowedLatencyMs) {
301
405
  const isBreached = threads > targetThresholdBreak;
302
406
  const stressFactor = isBreached ? Math.pow(threads / targetThresholdBreak, 1.5) : 1;
303
407
  const errorPool = [
408
+ //[cite: 2]
304
409
  `Error: ECONNREFUSED 127.0.0.1:5432 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1605:16)`,
410
+ //[cite: 2]
305
411
  `HTTP/1.1 504 Gateway Timeout on POST /api/v1/checkout - upstream socket drop after 15000ms`,
412
+ //[cite: 2]
306
413
  `TypeError: Cannot read properties of undefined (reading 'config_id') at Object.execute (${path.sep}app${path.sep}dist${path.sep}handler.js:42:19)`
414
+ //[cite: 2]
307
415
  ];
308
416
  for (let i = 0; i < totalRequests; i++) {
309
417
  const isError = Math.random() < (isBreached ? 0.05 : 1e-3);
@@ -315,13 +423,21 @@ function generateSimulationData(threads, durationSec, maxAllowedLatencyMs) {
315
423
  errorMessage = `[${(/* @__PURE__ */ new Date()).toISOString()}] ` + errorPool[Math.floor(Math.random() * errorPool.length)];
316
424
  }
317
425
  data.push({
426
+ //[cite: 2]
318
427
  durationMs: isError ? baseLatency * 0.1 : baseLatency,
428
+ //[cite: 2]
319
429
  timestampMs: startTime + Math.random() * (durationSec * 1e3),
430
+ //[cite: 2]
320
431
  dnsTimeMs: 1 + Math.random() * 0.9,
432
+ //[cite: 2]
321
433
  tcpTimeMs: 4 + Math.random() * 1.5,
434
+ //[cite: 2]
322
435
  tlsTimeMs: 6 + Math.random() * 1.8,
436
+ //[cite: 2]
323
437
  statusCode,
438
+ //[cite: 2]
324
439
  errorMessage
440
+ //[cite: 2]
325
441
  });
326
442
  }
327
443
  return data.sort((a, b) => a.timestampMs - b.timestampMs);
@@ -351,22 +467,32 @@ function processMetricsTelemetry(requests, durationSec) {
351
467
  const apdexScore = totalRequests === 0 ? 0 : (satisfied + tolerating / 2) / totalRequests;
352
468
  const bandwidthMb = totalRequests * 1.2 / durationSec / 10;
353
469
  return {
470
+ //[cite: 2]
354
471
  totalRequests,
472
+ //[cite: 2]
355
473
  requestsPerSecond: totalRequests / durationSec,
474
+ //[cite: 2]
356
475
  avgLatencyMs,
476
+ //[cite: 2]
357
477
  stdDevMs,
478
+ //[cite: 2]
358
479
  p95LatencyMs,
480
+ //[cite: 2]
359
481
  errorRate,
482
+ //[cite: 2]
360
483
  apdexScore,
484
+ //[cite: 2]
361
485
  c2xx,
362
486
  c3xx,
363
487
  c4xx,
364
488
  c5xx,
489
+ //[cite: 2]
365
490
  avgDnsMs,
366
491
  avgTcpMs,
367
492
  avgTlsMs,
368
493
  avgTtfbMs,
369
494
  bandwidthMb
495
+ //[cite: 2]
370
496
  };
371
497
  }
372
498
  function printMatrixDashboard(m, threads) {
@@ -438,11 +564,9 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
438
564
  <span style="background: ${sevBg}; color: #ffffff; padding: 0.2rem 0.5rem; border-radius: 4px; font-size: 0.7rem; font-weight: bold; letter-spacing: 0.05em;">${c.severity}</span>
439
565
  </td>
440
566
  <td style="padding: 1.25rem 0.75rem;">
441
- <!-- Abstract Template Blueprint Box -->
442
567
  <div style="background: #090d16; border-radius: 4px; padding: 0.6rem 0.8rem; border-left: 3px solid #1e293b; margin-bottom: 0.5rem;">
443
568
  <code style="color: #cbd5e1; font-family: monospace; font-size: 0.9rem; white-space: pre-wrap; word-break: break-all;">${cleanedTemplate}</code>
444
569
  </div>
445
- <!-- Trace Example Line -->
446
570
  <div style="color: #64748b; font-size: 0.8rem; font-family: monospace; padding-left: 0.2rem; line-height: 1.4;">
447
571
  <span style="color: #475569;">Real Example Trace:</span> ${rawTemplate}
448
572
  </div>
@@ -464,7 +588,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
464
588
  h1 { color: #38bdf8; margin: 0; font-size: 2rem; }
465
589
  .meta { color: #94a3b8; font-size: 0.9rem; margin-top: 0.5rem; }
466
590
 
467
- /* \u{1F3B4} CARDS DASHBOARD GRID SYSTEM */
468
591
  .cards-wrapper { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 1.5rem; }
469
592
  .metric-card { background: #131c2e; border: 1px solid #1e293b; border-radius: 6px; padding: 1.25rem; position: relative; }
470
593
  .card-title { font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.5rem; }
@@ -494,8 +617,10 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
494
617
  .badge-5xx { background: rgba(220, 38, 38, 0.2); color: #f87171; }
495
618
  .matrix-value { font-size: 1rem; font-weight: bold; color: #ffffff; }
496
619
 
497
- .graph-card { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.5rem; margin-bottom: 2rem; }
498
- .graph-title { font-size: 1.15rem; font-weight: 700; color: #ffffff; margin-bottom: 1.2rem; display: flex; align-items: center; gap: 0.5rem; }
620
+ /* \u{1F4CA} TWO-COLUMN CHART GRID */
621
+ .charts-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin-bottom: 2rem; }
622
+ .graph-card { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.5rem; }
623
+ .graph-title { font-size: 1.1rem; font-weight: 700; color: #ffffff; margin-bottom: 1.2rem; display: flex; align-items: center; gap: 0.5rem; }
499
624
 
500
625
  .card { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.5rem; }
501
626
  h3 { margin-top: 0; color: #cbd5e1; border-bottom: 1px solid #1e293b; padding-bottom: 0.5rem; }
@@ -512,7 +637,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
512
637
  <div class="meta">Target Script: <code>${config.targetScript}</code></div>
513
638
  </div>
514
639
 
515
- <!-- \u{1F3B4} METRICS CARDS GRID PANEL -->
516
640
  <div class="cards-wrapper">
517
641
  <div class="metric-card">
518
642
  <div class="card-title">Apdex Score (T: 50ms)</div>
@@ -576,11 +700,22 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
576
700
  </div>
577
701
  </div>
578
702
 
579
- <!-- \u{1F4C9} CORRELATION STREAM GRAPH CHART -->
580
- <div class="graph-card">
581
- <div class="graph-title">\u{1F504} Throughput, TTF Trend & Active Threads Concurrency Correlation</div>
582
- <div style="height: 320px; position: relative;">
583
- <canvas id="correlationChart"></canvas>
703
+ <!-- \u{1F4C9} SPLIT CHARTS SYSTEM -->
704
+ <div class="charts-grid">
705
+ <!-- Chart 1: Volume Streams -->
706
+ <div class="graph-card">
707
+ <div class="graph-title">\u{1F4CA} Throughput Velocity & Workload Volume</div>
708
+ <div style="height: 280px; position: relative;">
709
+ <canvas id="volumeChart"></canvas>
710
+ </div>
711
+ </div>
712
+
713
+ <!-- Chart 2: Concurrency & Health Trends -->
714
+ <div class="graph-card">
715
+ <div class="graph-title">\u{1F504} Active Concurrency (VUs) vs. Time-to-Failure (TTF) Trend</div>
716
+ <div style="height: 280px; position: relative;">
717
+ <canvas id="concurrencyChart"></canvas>
718
+ </div>
584
719
  </div>
585
720
  </div>
586
721
 
@@ -617,7 +752,9 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
617
752
 
618
753
  <script>
619
754
  const labels = ${JSON.stringify(labels)};
620
- new Chart(document.getElementById('correlationChart'), {
755
+
756
+ // \u{1F6E0}\uFE0F Chart 1 Setup: Throughput Bar Streams
757
+ new Chart(document.getElementById('volumeChart'), {
621
758
  type: 'bar',
622
759
  data: {
623
760
  labels: labels,
@@ -637,25 +774,45 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
637
774
  stack: 'requests',
638
775
  barPercentage: 0.95,
639
776
  categoryPercentage: 0.95
640
- },
777
+ }
778
+ ]
779
+ },
780
+ options: {
781
+ responsive: true,
782
+ maintainAspectRatio: false,
783
+ plugins: {
784
+ legend: { position: 'top', labels: { color: '#94a3b8', font: { size: 11 } } }
785
+ },
786
+ scales: {
787
+ x: { grid: { color: '#1e293b' }, ticks: { color: '#64748b' } },
788
+ y: { stacked: true, grid: { color: '#1e293b' }, ticks: { color: '#64748b' } }
789
+ }
790
+ }
791
+ });
792
+
793
+ // \u{1F6E0}\uFE0F Chart 2 Setup: Concurrency & TTF Correlated Slopes
794
+ new Chart(document.getElementById('concurrencyChart'), {
795
+ type: 'line',
796
+ data: {
797
+ labels: labels,
798
+ datasets: [
641
799
  {
642
800
  label: 'Active VU Threads',
643
801
  data: ${JSON.stringify(activeThreadsData)},
644
- type: 'line',
645
802
  borderColor: '#38bdf8',
646
- borderWidth: 2,
647
- pointRadius: 3,
648
- fill: false,
803
+ backgroundColor: 'rgba(56, 189, 248, 0.1)',
804
+ borderWidth: 2.5,
805
+ pointRadius: 4,
806
+ fill: true,
649
807
  yAxisID: 'yThreads'
650
808
  },
651
809
  {
652
810
  label: 'Time-to-Failure (TTF) Trend',
653
811
  data: ${JSON.stringify(ttfTrendData)},
654
- type: 'line',
655
812
  borderColor: '#f43f5e',
656
- borderWidth: 1.5,
657
- borderDash: [4, 4],
658
- pointRadius: 0,
813
+ borderWidth: 2,
814
+ borderDash: [5, 5],
815
+ pointRadius: 3,
659
816
  fill: false,
660
817
  yAxisID: 'yTtf'
661
818
  }
@@ -665,17 +822,13 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
665
822
  responsive: true,
666
823
  maintainAspectRatio: false,
667
824
  plugins: {
668
- legend: {
669
- position: 'top',
670
- labels: { color: '#94a3b8', boxWidth: 12, font: { size: 11 } }
671
- }
825
+ legend: { position: 'top', labels: { color: '#94a3b8', font: { size: 11 } } }
826
+ },
827
+ scales: {
828
+ x: { grid: { color: '#1e293b' }, ticks: { color: '#64748b' } },
829
+ y_threads: { position: 'left', grid: { color: '#1e293b' }, ticks: { color: '#38bdf8' }, title: { display: true, text: 'VUs / Threads', color: '#38bdf8' } },
830
+ y_ttf: { position: 'right', grid: { drawOnChartArea: false }, ticks: { color: '#f43f5e' }, title: { display: true, text: 'TTF Index / Latency ms', color: '#f43f5e' } }
672
831
  }
673
- },
674
- scales: {
675
- x: { grid: { color: '#1e293b' }, ticks: { color: '#64748b' } },
676
- y: { stacked: true, grid: { color: '#1e293b' }, ticks: { color: '#64748b' }, title: { display: true, text: 'Requests Volume', color: '#64748b' } },
677
- yThreads: { position: 'right', display: true, grid: { drawOnChartArea: false }, ticks: { color: '#38bdf8' }, title: { display: true, text: 'Active Threads', color: '#38bdf8' } },
678
- yTtf: { position: 'right', display: false, grid: { drawOnChartArea: false } }
679
832
  }
680
833
  });
681
834
  </script></body></html>`;
@@ -689,6 +842,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
689
842
  function printUsage() {
690
843
  console.log(`Blaze Core Performance Test CLI Engine
691
844
  Options:
692
- --threads <count> | --duration <seconds> | --agentic | --cluster-logs`);
845
+ --threads <count> | --duration <seconds> | --agentic | --cluster-logs | --correlate`);
693
846
  }
694
847
  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.0.22",
3
+ "version": "3.0.24",
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",