blaze-performance-tester 3.1.21 → 3.1.22

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
@@ -240,6 +240,13 @@ function calculateSeoImpactMetrics(avgLatencyMs) {
240
240
  }
241
241
  return { trafficLoss, status, crawlPenalty, color };
242
242
  }
243
+ function computeHealthScoreValue(apdex, errorRate, p95Latency, maxAllowedLatency) {
244
+ const apdexComponent = apdex * 50;
245
+ const errorComponent = Math.max(0, 1 - errorRate) * 30;
246
+ const latencyRatio = p95Latency / maxAllowedLatency;
247
+ const latencyComponent = Math.max(0, 1 - Math.min(1, latencyRatio)) * 20;
248
+ return Math.min(100, Math.max(0, Math.round(apdexComponent + errorComponent + latencyComponent)));
249
+ }
243
250
  async function runIntelligentAgenticStressTest(config) {
244
251
  console.log("\u{1F680} Initializing Intelligent Autonomous Load Agent...");
245
252
  const history = [];
@@ -327,20 +334,23 @@ async function runIntelligentAgenticStressTest(config) {
327
334
  const analyzer = new LogAnalyzer();
328
335
  semanticReport = analyzer.process(aggregateErrorLogs);
329
336
  }
337
+ const finalState = history[history.length - 1] || { apdex: 0, errorRate: 0, p95Latency: 0, throughput: 0 };
338
+ const healthScore = computeHealthScoreValue(finalState.apdex, finalState.errorRate, finalState.p95Latency, config.maxAllowedLatencyMs);
330
339
  const finalSummaryCards = {
331
- apdex: history[history.length - 1]?.apdex || 0,
332
- throughput: history[history.length - 1]?.throughput || 0,
340
+ apdex: finalState.apdex,
341
+ throughput: finalState.throughput,
333
342
  bandwidth: mathUtils.mean(globalMetricsAccumulator.bandwidths),
334
343
  ttfb: mathUtils.mean(globalMetricsAccumulator.ttfb),
335
344
  dns: mathUtils.mean(globalMetricsAccumulator.dns),
336
345
  tcp: mathUtils.mean(globalMetricsAccumulator.tcp),
337
346
  tls: mathUtils.mean(globalMetricsAccumulator.tls),
338
347
  stdDev: mathUtils.stdDev(globalMetricsAccumulator.latencies, mathUtils.mean(globalMetricsAccumulator.latencies)),
339
- saturationKneePoint: saturationKneePoint || history[history.length - 1]?.threads || 50
348
+ saturationKneePoint: saturationKneePoint || finalState.threads || 50,
349
+ healthScore
340
350
  };
341
- generateFinalAgentReport(history);
351
+ generateFinalAgentReport(history, healthScore);
342
352
  if (config.isSeo) {
343
- const finalLat = history[history.length - 1]?.avgLatency || finalSummaryCards.ttfb;
353
+ const finalLat = finalState.avgLatency || finalSummaryCards.ttfb;
344
354
  const seo = calculateSeoImpactMetrics(finalLat);
345
355
  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}].`);
346
356
  }
@@ -354,6 +364,8 @@ async function runStandardStressTest(config) {
354
364
  console.log(`\u{1F3CB}\uFE0F Running Standard Stress Test [Threads: ${config.threads} | Duration: ${config.durationSec}s]`);
355
365
  const { metrics, rawErrors, rawRequests } = await runBlazeCoreEngine(config);
356
366
  printMatrixDashboard(metrics, config.threads);
367
+ const healthScore = computeHealthScoreValue(metrics.apdexScore, metrics.errorRate, metrics.p95LatencyMs, config.maxAllowedLatencyMs);
368
+ console.log(`\u{1F49A} Unified Blaze Health Score: ${healthScore}/100`);
357
369
  const history = [{
358
370
  threads: config.threads,
359
371
  avgLatency: metrics.avgLatencyMs,
@@ -380,7 +392,8 @@ async function runStandardStressTest(config) {
380
392
  tcp: metrics.avgTcpMs,
381
393
  tls: metrics.avgTlsMs,
382
394
  stdDev: metrics.stdDevMs,
383
- saturationKneePoint: config.threads
395
+ saturationKneePoint: config.threads,
396
+ healthScore
384
397
  };
385
398
  const isPassed = metrics.apdexScore >= config.targetApdex && metrics.errorRate <= config.targetErrorRate;
386
399
  const verdictReason = isPassed ? "Static single-wave baseline checks concluded successfully without triggering health boundaries." : "Static verification loop completed with values exceeding defined quality thresholds.";
@@ -454,7 +467,7 @@ function processMetricsTelemetry(requests, durationSec) {
454
467
  const avgTlsMs = mathUtils.mean(requests.map((r) => r.tlsTimeMs || 0));
455
468
  const avgTtfbMs = avgDnsMs + avgTcpMs + avgTlsMs + avgLatencyMs * 0.3;
456
469
  let c1xx = 0, c2xx = 0, c3xx = 0, c4xx = 0, c5xx = 0;
457
- const codeCounts = { 400: 0, 401: 0, 403: 0, 404: 0, 429: 0, 500: 0, 502: 0, 503: 0, 504: 0 };
470
+ const codeCounts = { 400: 0, 401: 0, 403: 0, 404: 0, 429: 0, 500: 502, 502: 0, 503: 0, 504: 0 };
458
471
  requests.forEach((r) => {
459
472
  if (r.statusCode >= 100 && r.statusCode < 200) c1xx++;
460
473
  else if (r.statusCode >= 200 && r.statusCode < 300) c2xx++;
@@ -501,7 +514,7 @@ function printMatrixDashboard(m, threads) {
501
514
  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)} |`);
502
515
  console.log(`-----------------------------------------------------------------------------------------`);
503
516
  }
504
- function generateFinalAgentReport(history) {
517
+ function generateFinalAgentReport(history, score) {
505
518
  if (history.length === 0) return;
506
519
  const peakThroughput = Math.max(...history.map((h) => h.throughput));
507
520
  const cleanRuns = history.filter((h) => h.apdex >= 0.85 && h.errorRate <= 0.01);
@@ -509,6 +522,7 @@ function generateFinalAgentReport(history) {
509
522
  console.log("\n=======================================================");
510
523
  console.log("\u{1F9E0} INTELLIGENT AUTONOMOUS LOAD AGENT FINAL REPORT");
511
524
  console.log("=======================================================");
525
+ console.log(`\u{1F49A} Unified Blaze Health Score : ${score}/100`);
512
526
  console.log(`\u{1F3C6} Recommended Max Safe Concurrency : ${maxSafeThreads} allocation threads`);
513
527
  console.log(`\u{1F4A5} Infrastructure Failure Boundary : ${history[history.length - 1].threads} concurrency allocation`);
514
528
  console.log(`\u26A1 Peak Achieved Cluster Velocity : ${peakThroughput.toFixed(0)} req/sec`);
@@ -670,6 +684,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
670
684
  </div>
671
685
  `;
672
686
  }).join("");
687
+ const gaugeColor = cards.healthScore >= 90 ? "#10b981" : cards.healthScore >= 70 ? "#f59e0b" : "#ef4444";
673
688
  const htmlContent = `<!DOCTYPE html><html lang="en"><head>
674
689
  <meta charset="UTF-8">
675
690
  <title>Blaze Core Performance Report</title>
@@ -691,13 +706,16 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
691
706
  .card-value.purple { color: #a855f7; }
692
707
  .card-subtext { font-size: 0.8rem; color: #10b981; font-weight: 500; margin-left: 0.4rem; display: inline-block; }
693
708
 
694
- .top-layout-grid { display: grid; grid-template-columns: 1fr 400px; gap: 1.5rem; margin-bottom: 2rem; }
709
+ .top-layout-grid { display: grid; grid-template-columns: 1fr 280px 380px; gap: 1.5rem; margin-bottom: 2rem; }
695
710
  .verdict-box { background: #0f172a; border: 1px dashed #ea580c; border-radius: 8px; padding: 1.25rem; }
696
711
  .verdict-title { text-transform: uppercase; font-size: 0.85rem; font-weight: 700; color: #f97316; margin-bottom: 0.5rem; }
697
712
  .verdict-text { font-size: 0.95rem; line-height: 1.5; color: #e2e8f0; margin-bottom: 0.75rem; }
698
713
  .verdict-waves { background: #1f2937; border-radius: 6px; padding: 0.75rem 1rem; font-family: monospace; color: #9ca3af; font-size: 0.9rem; }
699
714
  .wave-item { margin: 0.25rem 0; }
700
715
 
716
+ .gauge-container-box { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.25rem; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; }
717
+ .gauge-title { font-size: 0.85rem; font-weight: bold; color: #94a3b8; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 1rem; }
718
+
701
719
  .matrix-box { background: #131c2e; border: 1px solid #1e293b; border-radius: 8px; padding: 1.25rem; }
702
720
  .matrix-title { font-size: 1.1rem; font-weight: bold; color: #ffffff; margin-bottom: 1rem; }
703
721
  .matrix-box .matrix-row { display: flex; justify-content: space-between; align-items: center; padding: 0.6rem 0; border-bottom: 1px solid #1e293b; }
@@ -772,6 +790,26 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
772
790
  <div class="verdict-waves">${waveListItems}</div>
773
791
  </div>
774
792
 
793
+ <!-- IMPLEMENTED CARD FEATURE 76: Executive Health Gauges Panel -->
794
+ <div class="gauge-container-box">
795
+ <div class="gauge-title">Blaze Run Health Score</div>
796
+ <div style="position: relative; width: 140px; height: 140px; display: flex; align-items: center; justify-content: center;">
797
+ <svg width="140" height="140" viewBox="0 0 140 140" style="transform: rotate(-90deg);">
798
+ <circle cx="70" cy="70" r="58" stroke="#1e293b" stroke-width="12" fill="transparent"/>
799
+ <circle cx="70" cy="70" r="58" stroke="${gaugeColor}" stroke-width="12" fill="transparent"
800
+ stroke-dasharray="364.4" stroke-dashoffset="${364.4 - 364.4 * cards.healthScore / 100}"
801
+ stroke-linecap="round" style="transition: stroke-dashoffset 1s ease-out;"/>
802
+ </svg>
803
+ <div style="position: absolute; text-align: center;">
804
+ <div style="font-size: 2.2rem; font-weight: 800; color: #ffffff; line-height: 1;">${cards.healthScore}</div>
805
+ <div style="font-size: 0.75rem; color: #64748b; font-weight: bold; margin-top: 0.2rem; text-transform: uppercase;">/ 100</div>
806
+ </div>
807
+ </div>
808
+ <div style="margin-top: 0.75rem; font-size: 0.8rem; color: #94a3b8; font-weight: 500;">
809
+ Composite Run Quality Engine Rating
810
+ </div>
811
+ </div>
812
+
775
813
  <div class="matrix-box">
776
814
  <div class="matrix-title">\u{1F4CB} HTTP Response Matrix</div>
777
815
  <div class="matrix-row">
@@ -795,7 +833,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
795
833
  <div class="matrix-value">${responseMatrix.total5xx}</div>
796
834
  </div>
797
835
 
798
- <!-- NEW SUBSECTION: Individual HTTP Status Code Breakdown Rates -->
799
836
  <div class="matrix-title" style="margin-top: 1.5rem; font-size: 0.85rem; border-top: 1px solid #1e293b; padding-top: 1rem; color: #94a3b8; text-transform: uppercase; letter-spacing: 0.05em;">
800
837
  \u{1F522} HTTP Status Code Breakdown Rate
801
838
  </div>
@@ -874,7 +911,6 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
874
911
  const baseThroughput = ${cards.throughput};
875
912
  const baseLatency = ${cards.ttfb};
876
913
 
877
- // Live Concurrency Adjuster interactive client logic
878
914
  const slider = document.getElementById('concurrencySlider');
879
915
  const sliderVal = document.getElementById('sliderValue');
880
916
  const simThroughput = document.getElementById('simThroughput');
@@ -980,9 +1016,9 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
980
1016
  responsive: true,
981
1017
  maintainAspectRatio: false,
982
1018
  plugins: {
983
- legend: { position: 'top', labels: { color: '#94a3b8', font: { size: 11 } } }
984
- },
985
- cutout: '65%'
1019
+ legend: { position: 'top', labels: { color: '#94a3b8', font: { size: 11 } } },
1020
+ cutout: '65%'
1021
+ }
986
1022
  }
987
1023
  });
988
1024
 
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blaze-performance-tester",
3
- "version": "3.1.21",
3
+ "version": "3.1.22",
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",