blaze-performance-tester 3.1.15 → 3.1.17

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
@@ -147,7 +147,6 @@ function parseArguments(args) {
147
147
  let maxThreads = 300;
148
148
  let maxAllowedLatencyMs = 800;
149
149
  let outputHtml = "blaze-dashboard.html";
150
- let apdexT = 50;
151
150
  const threadsIdx = args.indexOf("--threads");
152
151
  if (threadsIdx !== -1) threads = parseInt(args[threadsIdx + 1], 10);
153
152
  const durationIdx = args.indexOf("--duration");
@@ -160,8 +159,6 @@ function parseArguments(args) {
160
159
  if (maxThreadsIdx !== -1) maxThreads = parseInt(args[maxThreadsIdx + 1], 10);
161
160
  const outputIdx = args.indexOf("--output");
162
161
  if (outputIdx !== -1) outputHtml = args[outputIdx + 1];
163
- const apdexTIdx = args.indexOf("--apdex-t");
164
- if (apdexTIdx !== -1) apdexT = parseFloat(args[apdexTIdx + 1]);
165
162
  const positionalNums = args.slice(1).filter((arg) => !arg.startsWith("-")).map(Number).filter((n) => !isNaN(n));
166
163
  if (positionalNums.length > 0 && threadsIdx === -1 && !isAgentic) threads = positionalNums[0];
167
164
  if (positionalNums.length > 1 && durationIdx === -1 && !isAgentic) durationSec = positionalNums[1];
@@ -192,8 +189,7 @@ function parseArguments(args) {
192
189
  maxThreads,
193
190
  stepSize: 15,
194
191
  maxAllowedLatencyMs,
195
- outputHtml,
196
- apdexT
192
+ outputHtml
197
193
  };
198
194
  }
199
195
  async function runBlazeCoreEngine(config) {
@@ -211,7 +207,7 @@ async function runBlazeCoreEngine(config) {
211
207
  }
212
208
  const warmUpCutoff = Math.floor(rawRequests.length * 0.1);
213
209
  const steadyStateRequests = rawRequests.slice(warmUpCutoff);
214
- const metrics = processMetricsTelemetry(steadyStateRequests.length > 0 ? steadyStateRequests : rawRequests, config.durationSec, config.apdexT);
210
+ const metrics = processMetricsTelemetry(steadyStateRequests.length > 0 ? steadyStateRequests : rawRequests, config.durationSec);
215
211
  const rawErrors = rawRequests.filter((r) => r.errorMessage).map((r) => r.errorMessage);
216
212
  resolve2({ metrics, rawErrors, rawRequests: steadyStateRequests.length > 0 ? steadyStateRequests : rawRequests });
217
213
  }, 1e3);
@@ -223,7 +219,7 @@ async function runIntelligentAgenticStressTest(config) {
223
219
  let aggregateErrorLogs = [];
224
220
  let lastRawRequests = [];
225
221
  let total1xx = 0, total2xx = 0, total3xx = 0, total4xx = 0, total5xx = 0;
226
- let globalMetricsAccumulator = { dns: [], tcp: [], tls: [], ttfb: [], latencies: [], bandwidths: [], lcp: [], fid: [], cls: [] };
222
+ let globalMetricsAccumulator = { dns: [], tcp: [], tls: [], ttfb: [], latencies: [], bandwidths: [] };
227
223
  let currentThreads = Math.min(config.maxThreads, Math.max(5, Math.floor(config.maxThreads * 0.2)));
228
224
  let baseStep = config.stepSize;
229
225
  let isStable = true;
@@ -247,9 +243,6 @@ async function runIntelligentAgenticStressTest(config) {
247
243
  globalMetricsAccumulator.ttfb.push(metrics.avgTtfbMs);
248
244
  globalMetricsAccumulator.latencies.push(metrics.avgLatencyMs);
249
245
  globalMetricsAccumulator.bandwidths.push(metrics.bandwidthMb);
250
- globalMetricsAccumulator.lcp.push(metrics.lcpMs);
251
- globalMetricsAccumulator.fid.push(metrics.fidMs);
252
- globalMetricsAccumulator.cls.push(metrics.clsScore);
253
246
  const currentState = {
254
247
  threads: currentThreads,
255
248
  avgLatency: metrics.avgLatencyMs,
@@ -258,10 +251,7 @@ async function runIntelligentAgenticStressTest(config) {
258
251
  apdex: metrics.apdexScore,
259
252
  throughput: metrics.requestsPerSecond,
260
253
  successRequests: metrics.c2xx + metrics.c3xx,
261
- failedRequests: metrics.c4xx + metrics.c5xx,
262
- lcp: metrics.lcpMs,
263
- fid: metrics.fidMs,
264
- cls: metrics.clsScore
254
+ failedRequests: metrics.c4xx + metrics.c5xx
265
255
  };
266
256
  printMatrixDashboard(metrics, currentThreads);
267
257
  history.push(currentState);
@@ -315,10 +305,7 @@ async function runIntelligentAgenticStressTest(config) {
315
305
  tls: mathUtils.mean(globalMetricsAccumulator.tls),
316
306
  stdDev: mathUtils.stdDev(globalMetricsAccumulator.latencies, mathUtils.mean(globalMetricsAccumulator.latencies)),
317
307
  saturationKneePoint: saturationKneePoint || history[history.length - 1]?.threads || 50,
318
- vuRampUpVelocity,
319
- lcp: mathUtils.mean(globalMetricsAccumulator.lcp),
320
- fid: mathUtils.mean(globalMetricsAccumulator.fid),
321
- cls: mathUtils.mean(globalMetricsAccumulator.cls)
308
+ vuRampUpVelocity
322
309
  };
323
310
  generateFinalAgentReport(history);
324
311
  exportHtmlDashboard(history, config, verdictReason, semanticReport, { total1xx, total2xx, total3xx, total4xx, total5xx }, finalSummaryCards, lastRawRequests);
@@ -335,10 +322,7 @@ async function runStandardStressTest(config) {
335
322
  apdex: metrics.apdexScore,
336
323
  throughput: metrics.requestsPerSecond,
337
324
  successRequests: metrics.c2xx + metrics.c3xx,
338
- failedRequests: metrics.c4xx + metrics.c5xx,
339
- lcp: metrics.lcpMs,
340
- fid: metrics.fidMs,
341
- cls: metrics.clsScore
325
+ failedRequests: metrics.c4xx + metrics.c5xx
342
326
  }];
343
327
  let semanticReport = null;
344
328
  if (config.clusterLogs) {
@@ -357,10 +341,7 @@ async function runStandardStressTest(config) {
357
341
  tls: metrics.avgTlsMs,
358
342
  stdDev: metrics.stdDevMs,
359
343
  saturationKneePoint: config.threads,
360
- vuRampUpVelocity: config.threads / config.durationSec,
361
- lcp: metrics.lcpMs,
362
- fid: metrics.fidMs,
363
- cls: metrics.clsScore
344
+ vuRampUpVelocity: config.threads / config.durationSec
364
345
  };
365
346
  const isPassed = metrics.apdexScore >= config.targetApdex && metrics.errorRate <= config.targetErrorRate;
366
347
  const verdictReason = isPassed ? "Static single-wave baseline checks concluded successfully without triggering health boundaries." : "Static verification loop completed with values exceeding defined quality thresholds.";
@@ -413,7 +394,7 @@ function generateSimulationData(threads, durationSec, maxAllowedLatencyMs) {
413
394
  }
414
395
  return data.sort((a, b) => a.timestampMs - b.timestampMs);
415
396
  }
416
- function processMetricsTelemetry(requests, durationSec, apdexT) {
397
+ function processMetricsTelemetry(requests, durationSec) {
417
398
  const totalRequests = requests.length;
418
399
  const durations = requests.map((r) => r.durationMs);
419
400
  const avgLatencyMs = mathUtils.mean(durations);
@@ -433,13 +414,11 @@ function processMetricsTelemetry(requests, durationSec, apdexT) {
433
414
  });
434
415
  const errorCount = c4xx + c5xx;
435
416
  const errorRate = totalRequests === 0 ? 0 : errorCount / totalRequests;
436
- const satisfied = requests.filter((r) => r.durationMs <= apdexT && r.statusCode < 400).length;
437
- const tolerating = requests.filter((r) => r.durationMs > apdexT && r.durationMs <= apdexT * 4 && r.statusCode < 400).length;
417
+ const T = 50;
418
+ const satisfied = requests.filter((r) => r.durationMs <= T && r.statusCode < 400).length;
419
+ const tolerating = requests.filter((r) => r.durationMs > T && r.durationMs <= T * 4 && r.statusCode < 400).length;
438
420
  const apdexScore = totalRequests === 0 ? 0 : (satisfied + tolerating / 2) / totalRequests;
439
421
  const bandwidthMb = totalRequests * 1.2 / durationSec / 10;
440
- const lcpMs = avgTtfbMs * 1.6 + (p95LatencyMs - avgLatencyMs) * 0.4;
441
- const fidMs = Math.max(1.5, stdDevMs * 0.18 + errorRate * 60);
442
- const clsScore = Math.min(0.5, errorRate * 0.25 + (avgLatencyMs > 400 ? 0.08 : 0.01));
443
422
  return {
444
423
  totalRequests,
445
424
  requestsPerSecond: totalRequests / durationSec,
@@ -457,10 +436,7 @@ function processMetricsTelemetry(requests, durationSec, apdexT) {
457
436
  avgTcpMs,
458
437
  avgTlsMs,
459
438
  avgTtfbMs,
460
- bandwidthMb,
461
- lcpMs,
462
- fidMs,
463
- clsScore
439
+ bandwidthMb
464
440
  };
465
441
  }
466
442
  function printMatrixDashboard(m, threads) {
@@ -470,8 +446,6 @@ function printMatrixDashboard(m, threads) {
470
446
  console.log(`-----------------------------------------------------------------------------------------`);
471
447
  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)} |`);
472
448
  console.log(`-----------------------------------------------------------------------------------------`);
473
- console.log(`| Simulated Web Vitals Equivalent -> LCP: ${m.lcpMs.toFixed(0)}ms | FID: ${m.fidMs.toFixed(1)}ms | CLS: ${m.clsScore.toFixed(3)} |`);
474
- console.log(`-----------------------------------------------------------------------------------------`);
475
449
  }
476
450
  function generateFinalAgentReport(history) {
477
451
  if (history.length === 0) return;
@@ -493,7 +467,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
493
467
  const activeThreadsData = history.map((h) => h.threads);
494
468
  const ttfTrendData = history.map((h) => h.avgLatency * 1.1);
495
469
  const waveListItems = history.map((h) => {
496
- return `<div class="wave-item">Wave (${h.threads} VUs): P95 ${h.p95Latency.toFixed(1)}ms, Errors ${(h.errorRate * 100).toFixed(1)}%, LCP ${h.lcp.toFixed(0)}ms</div>`;
470
+ return `<div class="wave-item">Wave (${h.threads} VUs): P95 ${h.p95Latency.toFixed(1)}ms, Errors ${(h.errorRate * 100).toFixed(1)}%</div>`;
497
471
  }).join("");
498
472
  const estimatedMonthlyCost = (cards.throughput * 0.045 * 24 * 30).toFixed(2);
499
473
  const recommendedCpuCores = Math.max(2, Math.ceil(cards.saturationKneePoint / 75));
@@ -503,12 +477,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
503
477
  x: Number(((r.timestampMs - firstTimestamp) / 1e3).toFixed(2)),
504
478
  y: Number(((r.dnsTimeMs || 0) + (r.tcpTimeMs || 0) + (r.tlsTimeMs || 0) + r.durationMs * 0.3).toFixed(1))
505
479
  }));
506
- const getLcpStatus = (val) => val <= 2500 ? { label: "Good", cls: "green" } : val <= 4e3 ? { label: "Needs Imp.", cls: "orange" } : { label: "Poor", cls: "badge-fail" };
507
- const getFidStatus = (val) => val <= 100 ? { label: "Good", cls: "green" } : val <= 300 ? { label: "Needs Imp.", cls: "orange" } : { label: "Poor", cls: "badge-fail" };
508
- const getClsStatus = (val) => val <= 0.1 ? { label: "Good", cls: "green" } : val <= 0.25 ? { label: "Needs Imp.", cls: "orange" } : { label: "Poor", cls: "badge-fail" };
509
- const lcpStat = getLcpStatus(cards.lcp);
510
- const fidStat = getFidStatus(cards.fid);
511
- const clsStat = getClsStatus(cards.cls);
512
480
  let logClustersHtml = "";
513
481
  if (semanticReport) {
514
482
  const totalLogCount = semanticReport.clusters.reduce((sum, c) => sum + c.count, 0);
@@ -635,7 +603,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
635
603
  h1 { color: #38bdf8; margin: 0; font-size: 2rem; }
636
604
  .meta { color: #94a3b8; font-size: 0.9rem; margin-top: 0.5rem; }
637
605
 
638
- .section-title { font-size: 1.2rem; color: #cbd5e1; font-weight: bold; margin: 2rem 0 1rem 0; padding-bottom: 0.4rem; border-bottom: 1px solid #1e293b; }
639
606
  .cards-wrapper { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 1.5rem; }
640
607
  .metric-card { background: #131c2e; border: 1px solid #1e293b; border-radius: 6px; padding: 1.25rem; position: relative; }
641
608
  .card-title { font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.5rem; }
@@ -645,9 +612,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
645
612
  .card-value.orange { color: #f97316; }
646
613
  .card-value.purple { color: #a855f7; }
647
614
  .card-value.cyan { color: #38bdf8; }
648
- .card-subtext { font-size: 0.8rem; font-weight: 500; margin-left: 0.4rem; display: inline-block; }
649
- .card-subtext.green { color: #10b981; }
650
- .card-subtext.orange { color: #f97316; }
615
+ .card-subtext { font-size: 0.8rem; color: #10b981; font-weight: 500; margin-left: 0.4rem; display: inline-block; }
651
616
 
652
617
  .top-layout-grid { display: grid; grid-template-columns: 1fr 400px; gap: 1.5rem; margin-bottom: 2rem; }
653
618
  .verdict-box { background: #0f172a; border: 1px dashed #ea580c; border-radius: 8px; padding: 1.25rem; }
@@ -688,11 +653,10 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
688
653
  <div class="meta">Target Script: <code>${config.targetScript}</code></div>
689
654
  </div>
690
655
 
691
- <div class="section-title">\u{1F4CA} Core Server Metrics & Apdex Verification</div>
692
656
  <div class="cards-wrapper">
693
657
  <div class="metric-card">
694
- <div class="card-title">Apdex Score (T: ${config.apdexT}ms)</div>
695
- <div class="card-value green">${cards.apdex.toFixed(2)}<span class="card-subtext green">(Target Verified)</span></div>
658
+ <div class="card-title">Apdex Score (T: 50ms)</div>
659
+ <div class="card-value green">${cards.apdex.toFixed(2)}<span class="card-subtext">(Good)</span></div>
696
660
  </div>
697
661
  <div class="metric-card">
698
662
  <div class="card-title">Throughput</div>
@@ -711,28 +675,23 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
711
675
  <div class="card-value cyan">${cards.vuRampUpVelocity.toFixed(1)}<span class="unit">VUs/s</span></div>
712
676
  </div>
713
677
  <div class="metric-card">
714
- <div class="card-title">Stability (Std Dev)</div>
715
- <div class="card-value">&plusmn;${cards.stdDev.toFixed(1)}<span class="unit">ms</span></div>
678
+ <div class="card-title">DNS Lookup</div>
679
+ <div class="card-value">${cards.dns.toFixed(2)}<span class="unit">ms</span></div>
716
680
  </div>
717
- </div>
718
-
719
- <div class="section-title">\u{1F310} Simulated Browser Core Web Vitals Equivalent</div>
720
- <div class="cards-wrapper">
721
681
  <div class="metric-card">
722
- <div class="card-title">Largest Contentful Paint (LCP)</div>
723
- <div class="card-value">${cards.lcp.toFixed(0)}<span class="unit">ms</span><span class="card-subtext ${lcpStat.cls}">(${lcpStat.label})</span></div>
682
+ <div class="card-title">TCP Connect</div>
683
+ <div class="card-value">${cards.tcp.toFixed(2)}<span class="unit">ms</span></div>
724
684
  </div>
725
685
  <div class="metric-card">
726
- <div class="card-title">First Input Delay (FID)</div>
727
- <div class="card-value">${cards.fid.toFixed(1)}<span class="unit">ms</span><span class="card-subtext ${fidStat.cls}">(${fidStat.label})</span></div>
686
+ <div class="card-title">TLS Handshake</div>
687
+ <div class="card-value">${cards.tls.toFixed(2)}<span class="unit">ms</span></div>
728
688
  </div>
729
689
  <div class="metric-card">
730
- <div class="card-title">Cumulative Layout Shift (CLS)</div>
731
- <div class="card-value">${cards.cls.toFixed(3)}<span class="card-subtext ${clsStat.cls}">(${clsStat.label})</span></div>
690
+ <div class="card-title">Stability (Std Dev)</div>
691
+ <div class="card-value">&plusmn;${cards.stdDev.toFixed(1)}<span class="unit">ms</span></div>
732
692
  </div>
733
693
  </div>
734
694
 
735
- <div class="section-title">\u26A1 Diagnostic Breakdowns</div>
736
695
  <div class="top-layout-grid">
737
696
  <div class="verdict-box">
738
697
  <div class="verdict-title">\u{1F916} AI Stress-Testing Agent Verdict</div>
@@ -804,7 +763,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
804
763
  <th>Throughput</th>
805
764
  <th>Avg Latency</th>
806
765
  <th>P95 Latency</th>
807
- <th>Simulated LCP</th>
808
766
  <th>Error Rate</th>
809
767
  <th>Status</th>
810
768
  </tr>
@@ -817,7 +775,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
817
775
  <td>${h.throughput.toFixed(0)} req/sec</td>
818
776
  <td>${h.avgLatency.toFixed(1)} ms</td>
819
777
  <td>${h.p95Latency.toFixed(1)} ms</td>
820
- <td>${h.lcp.toFixed(0)} ms</td>
821
778
  <td>${(h.errorRate * 100).toFixed(2)}%</td>
822
779
  <td><span class="badge ${isPassed ? "badge-success" : "badge-fail"}">${isPassed ? "SLO PASS" : "SLO BREACH"}</span></td>
823
780
  </tr>`;
@@ -990,6 +947,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
990
947
  function printUsage() {
991
948
  console.log(`Blaze Core Performance Test CLI Engine
992
949
  Options:
993
- --threads <count> | --duration <seconds> | --agentic | --cluster-logs | --correlate | --apdex-t <ms>`);
950
+ --threads <count> | --duration <seconds> | --agentic | --cluster-logs | --correlate`);
994
951
  }
995
952
  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.15",
3
+ "version": "3.1.17",
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",