blaze-performance-tester 3.1.51 → 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 +99 -9
- package/dist/index.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
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
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
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(
|
|
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
|