blaze-performance-tester 3.1.52 → 3.1.54

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
@@ -807,6 +807,30 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
807
807
  </div>
808
808
  </div>
809
809
  </div>`;
810
+ const nlpQueryEngineHtml = `
811
+ <div class="card" style="margin-top: 2rem; background: #131c2e; border: 1px solid #0ea5e9; border-left: 4px solid #0ea5e9;">
812
+ <h3 style="color: #0ea5e9; display: flex; align-items: center; gap: 0.5rem; font-size: 1.2rem; margin-bottom: 0.5rem; border-bottom: none; padding-bottom: 0;">
813
+ \u{1F916} Natural Language Telemetry Insights Query Engine
814
+ </h3>
815
+ <p style="color: #94a3b8; font-size: 0.9rem; margin: 0 0 1rem 0;">
816
+ Ask questions of your load test results using natural phrasing to isolate and filter metric rows dynamically.
817
+ </p>
818
+ <div style="display: flex; gap: 0.75rem; margin-bottom: 0.75rem;">
819
+ <input type="text" id="nlpQueryInput" placeholder="e.g., show me tiers where latency > 40ms or error rate > 0%"
820
+ style="flex: 1; background: #090d16; border: 1px solid #1e293b; border-radius: 6px; padding: 0.75rem 1rem; color: #ffffff; font-size: 0.95rem; outline: none; transition: border-color 0.2s;">
821
+ <button id="nlpQueryBtn" style="background: #0ea5e9; color: #ffffff; border: none; border-radius: 6px; padding: 0.75rem 1.5rem; font-weight: 600; cursor: pointer; transition: background 0.2s;">
822
+ Query Matrix
823
+ </button>
824
+ </div>
825
+ <div style="display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center;">
826
+ <span style="font-size: 0.8rem; color: #64748b; font-weight: bold; text-transform: uppercase; letter-spacing: 0.05em;">Suggestions:</span>
827
+ <button onclick="setNlpQuery('Show P95 latency > 50ms')" style="background: #1e293b; color: #cbd5e1; border: 1px solid #334155; border-radius: 4px; padding: 0.25rem 0.5rem; font-size: 0.8rem; cursor: pointer;">P95 Latency > 50ms</button>
828
+ <button onclick="setNlpQuery('Find tiers with errors > 0%')" style="background: #1e293b; color: #cbd5e1; border: 1px solid #334155; border-radius: 4px; padding: 0.25rem 0.5rem; font-size: 0.8rem; cursor: pointer;">Errors > 0%</button>
829
+ <button onclick="setNlpQuery('High concurrency > 25 VUs')" style="background: #1e293b; color: #cbd5e1; border: 1px solid #334155; border-radius: 4px; padding: 0.25rem 0.5rem; font-size: 0.8rem; cursor: pointer;">Concurrency > 25 VUs</button>
830
+ <button onclick="setNlpQuery('')" style="background: #1c1917; color: #f43f5e; border: 1px solid #44403c; border-radius: 4px; padding: 0.25rem 0.5rem; font-size: 0.8rem; cursor: pointer;">Reset Filter</button>
831
+ </div>
832
+ <div id="nlpQueryFeedback" style="margin-top: 0.75rem; font-size: 0.85rem; color: #38bdf8;"></div>
833
+ </div>`;
810
834
  const breakdownRates = responseMatrix.breakdownRates || {};
811
835
  const breakdownGridHtml = [400, 401, 403, 404, 429, 500, 502, 503, 504].map((code) => {
812
836
  const rate = breakdownRates[code] || 0;
@@ -1013,8 +1037,10 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1013
1037
  </div>
1014
1038
  </div>
1015
1039
  </div>
1040
+
1041
+ ${nlpQueryEngineHtml}
1016
1042
 
1017
- <div class="card">
1043
+ <div class="card" style="margin-top: 2rem;">
1018
1044
  <h3>Telemetry Matrix Logs</h3>
1019
1045
  <table>
1020
1046
  <thead>
@@ -1027,7 +1053,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1027
1053
  <th>Status</th>
1028
1054
  </tr>
1029
1055
  </thead>
1030
- <tbody>
1056
+ <tbody id="telemetryTableBody">
1031
1057
  ${history.map((h) => {
1032
1058
  const isPassed = h.apdex >= config.targetApdex && h.errorRate <= config.targetErrorRate;
1033
1059
  return `<tr>
@@ -1049,6 +1075,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1049
1075
  </div>
1050
1076
 
1051
1077
  <script>
1078
+ const telemetryHistory = ${JSON.stringify(history)};
1052
1079
  const labels = ${JSON.stringify(labels)};
1053
1080
  const baseThroughput = ${cards.throughput};
1054
1081
  const baseLatency = ${cards.ttfb};
@@ -1058,12 +1085,75 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1058
1085
  const simThroughput = document.getElementById('simThroughput');
1059
1086
  const simLatency = document.getElementById('simLatency');
1060
1087
 
1061
- slider.addEventListener('input', (e) => {
1062
- const val = parseInt(e.target.value, 10);
1063
- sliderVal.textContent = val;
1064
- const factor = val / ${config.threads || 10};
1065
- simThroughput.textContent = (baseThroughput * Math.min(factor, 2.5)).toFixed(0) + '/s';
1066
- simLatency.textContent = (baseLatency * Math.pow(factor, 0.8)).toFixed(1) + 'ms';
1088
+ if (slider) {
1089
+ slider.addEventListener('input', (e) => {
1090
+ const val = parseInt(e.target.value, 10);
1091
+ sliderVal.textContent = val;
1092
+ const factor = val / ${config.threads || 10};
1093
+ simThroughput.textContent = (baseThroughput * Math.min(factor, 2.5)).toFixed(0) + '/s';
1094
+ simLatency.textContent = (baseLatency * Math.pow(factor, 0.8)).toFixed(1) + 'ms';
1095
+ });
1096
+ }
1097
+
1098
+ // Client-side NLP Parser Engine Execution Implementation
1099
+ function executeNlpQuery(queryString) {
1100
+ const q = queryString.toLowerCase().trim();
1101
+ const rows = document.querySelectorAll('#telemetryTableBody tr');
1102
+ const feedback = document.getElementById('nlpQueryFeedback');
1103
+
1104
+ let filterFn = (row, data) => true;
1105
+ const numMatch = q.match(/(d+(?:.d+)?)/);
1106
+ const targetNum = numMatch ? parseFloat(numMatch[1]) : null;
1107
+
1108
+ const isGreater = q.includes('>') || q.includes('greater') || q.includes('above') || q.includes('more');
1109
+ const isLess = q.includes('<') || q.includes('less') || q.includes('below') || q.includes('under');
1110
+
1111
+ if (q.includes('latency') || q.includes('p95') || q.includes('ms')) {
1112
+ if (targetNum !== null) {
1113
+ filterFn = (row, data) => isLess ? (data.p95Latency < targetNum) : (data.p95Latency > targetNum);
1114
+ } else {
1115
+ filterFn = (row, data) => data.p95Latency > 0;
1116
+ }
1117
+ } else if (q.includes('error') || q.includes('fail') || q.includes('%')) {
1118
+ if (targetNum !== null) {
1119
+ const searchVal = q.includes('%') ? targetNum / 100 : targetNum;
1120
+ filterFn = (row, data) => isLess ? (data.errorRate < searchVal) : (data.errorRate > searchVal);
1121
+ } else {
1122
+ filterFn = (row, data) => data.errorRate > 0;
1123
+ }
1124
+ } else if (q.includes('concurrency') || q.includes('thread') || q.includes('vu')) {
1125
+ if (targetNum !== null) {
1126
+ filterFn = (row, data) => isLess ? (data.threads < targetNum) : (data.threads > targetNum);
1127
+ }
1128
+ }
1129
+
1130
+ let matchCount = 0;
1131
+ rows.forEach((row, idx) => {
1132
+ const data = telemetryHistory[idx];
1133
+ if (!data) return;
1134
+ if (filterFn(row, data)) {
1135
+ row.style.display = '';
1136
+ row.style.background = q !== '' ? 'rgba(14, 165, 233, 0.15)' : '';
1137
+ matchCount++;
1138
+ } else {
1139
+ row.style.display = 'none';
1140
+ }
1141
+ });
1142
+
1143
+ feedback.innerHTML = q === '' ? '' : '\u{1F50D} Match verification resolved <strong>' + matchCount + '</strong> parameters inside telemetry array.'; }
1144
+
1145
+ function setNlpQuery(str) {
1146
+ const input = document.getElementById('nlpQueryInput');
1147
+ input.value = str;
1148
+ executeNlpQuery(str);
1149
+ }
1150
+
1151
+ document.getElementById('nlpQueryBtn').addEventListener('click', () => {
1152
+ executeNlpQuery(document.getElementById('nlpQueryInput').value);
1153
+ });
1154
+
1155
+ document.getElementById('nlpQueryInput').addEventListener('keyup', (e) => {
1156
+ if (e.key === 'Enter') executeNlpQuery(e.target.value);
1067
1157
  });
1068
1158
 
1069
1159
  new Chart(document.getElementById('volumeChart'), {
@@ -1131,7 +1221,7 @@ function exportHtmlDashboard(history, config, verdictReason, semanticReport, res
1131
1221
  const threadStep = ${config.stepSize || 15};
1132
1222
 
1133
1223
  for (let i = 1; i <= 3; i++) {
1134
- extendedLabels.push(\`+\${i * 5}s (AI Forecast)\`);
1224
+ extendedLabels.push('+' + (i * 5) + 's (AI Forecast)');
1135
1225
  extendedThreads.push(lastThreads + (threadStep * i));
1136
1226
  extendedTtf.push(null);
1137
1227
  aiForecastData.push(Number((slope * (historicalCount + i - 1) + intercept).toFixed(1)));
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blaze-performance-tester",
3
- "version": "3.1.52",
3
+ "version": "3.1.54",
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",