|
13 | 13 | var latencyExpandedRows = Object.create(null); |
14 | 14 | var latestAuditRefreshRequest = 0; |
15 | 15 | var lastSeenTotalRequests = null; |
| 16 | + var captureParamsEnabled = null; |
| 17 | + var latestToolLatencySummary = Object.create(null); |
16 | 18 |
|
17 | 19 | // --- Theme --- |
18 | 20 | var THEME_COLORS = { |
|
245 | 247 | return document.getElementById(id); |
246 | 248 | } |
247 | 249 |
|
| 250 | + function paramsCaptureDisabled() { |
| 251 | + return captureParamsEnabled === false; |
| 252 | + } |
| 253 | + |
| 254 | + function renderCaptureParamsDisabledHint(tbody) { |
| 255 | + var hint = document.createElement("tr"); |
| 256 | + hint.className = "param-disabled-hint-row"; |
| 257 | + hint.innerHTML = "<td colspan='8'>Parameter pattern capture is disabled. Enable <code>metrics.capture_params: true</code> in Web UI config to view parameter data.</td>"; |
| 258 | + tbody.appendChild(hint); |
| 259 | + } |
| 260 | + |
| 261 | + function loadDashboardConfig() { |
| 262 | + fetch("/api/config") |
| 263 | + .then(function (r) { return r.json(); }) |
| 264 | + .then(function (data) { |
| 265 | + var metricsConfig = data && typeof data === "object" ? data.metrics : null; |
| 266 | + if (metricsConfig && typeof metricsConfig.capture_params === "boolean") { |
| 267 | + captureParamsEnabled = metricsConfig.capture_params; |
| 268 | + } else { |
| 269 | + captureParamsEnabled = null; |
| 270 | + } |
| 271 | + updateLatencyTable(latestToolLatencySummary); |
| 272 | + }) |
| 273 | + .catch(function () { |
| 274 | + captureParamsEnabled = null; |
| 275 | + }); |
| 276 | + } |
| 277 | + |
248 | 278 | // --- Chart Initialization --- |
249 | 279 | function initCharts() { |
250 | 280 | // Tool usage bar chart |
|
538 | 568 | Object.keys(latencyExpandedRows).forEach(function (tool) { |
539 | 569 | expandedRows[tool] = true; |
540 | 570 | }); |
| 571 | + latestToolLatencySummary = toolLatency || {}; |
| 572 | + var paramsDisabled = paramsCaptureDisabled(); |
541 | 573 | var nextExpandedRows = Object.create(null); |
542 | 574 | tbody.innerHTML = ""; |
543 | | - var tools = Object.keys(toolLatency).sort(); |
| 575 | + var tools = Object.keys(latestToolLatencySummary).sort(); |
544 | 576 | if (tools.length === 0) { |
545 | 577 | latencyExpandedRows = Object.create(null); |
546 | 578 | tbody.innerHTML = "<tr><td colspan='8' style='text-align:center;color:#8b949e'>No latency data</td></tr>"; |
547 | 579 | return; |
548 | 580 | } |
| 581 | + if (paramsDisabled) { |
| 582 | + renderCaptureParamsDisabledHint(tbody); |
| 583 | + } |
549 | 584 | tools.forEach(function (tool) { |
550 | | - var s = toolLatency[tool]; |
| 585 | + var s = latestToolLatencySummary[tool]; |
551 | 586 | var rowId = "param-row-" + tool.replace(/[^a-zA-Z0-9]/g, "_"); |
| 587 | + var toggleHtml = "<button class='param-toggle-btn' data-tool='" + tool + "' " |
| 588 | + + "data-target='" + rowId + "' title='Show parameter patterns' " |
| 589 | + + "aria-expanded='false'>▶</button> "; |
| 590 | + if (paramsDisabled) { |
| 591 | + toggleHtml = "<button class='param-toggle-btn param-toggle-btn-disabled' title='Enable metrics.capture_params to view parameter patterns' " |
| 592 | + + "aria-disabled='true' disabled>▶</button> "; |
| 593 | + } |
552 | 594 | var tr = document.createElement("tr"); |
553 | 595 | tr.innerHTML = "<td>" |
554 | | - + "<button class='param-toggle-btn' data-tool='" + tool + "' " |
555 | | - + "data-target='" + rowId + "' title='Show parameter patterns' " |
556 | | - + "aria-expanded='false'>▶</button> " + tool |
| 596 | + + toggleHtml + tool |
557 | 597 | + "</td>" |
558 | 598 | + "<td>" + s.count + "</td>" |
559 | 599 | + "<td>" + s.avg_ms.toFixed(1) + "</td>" |
|
568 | 608 | detailTr.id = rowId; |
569 | 609 | detailTr.className = "param-detail-row"; |
570 | 610 | detailTr.style.display = "none"; |
| 611 | + var detailHtml = "<em style='color:#8b949e'>Loading\u2026</em>"; |
| 612 | + if (paramsDisabled) { |
| 613 | + detailHtml = "<em style='color:#8b949e'>Parameter capture is disabled. Enable <code>metrics.capture_params: true</code> in Web UI config.</em>"; |
| 614 | + } |
571 | 615 | detailTr.innerHTML = "<td colspan='8'><div class='param-patterns-container' id='patterns-" + rowId + "'>" |
572 | | - + "<em style='color:#8b949e'>Loading\u2026</em></div></td>"; |
| 616 | + + detailHtml + "</div></td>"; |
573 | 617 | tbody.appendChild(detailTr); |
574 | 618 |
|
575 | | - if (expandedRows[tool]) { |
| 619 | + if (!paramsDisabled && expandedRows[tool]) { |
576 | 620 | detailTr.style.display = ""; |
577 | 621 | var toggleBtn = tr.querySelector(".param-toggle-btn"); |
578 | 622 | if (toggleBtn) { |
|
593 | 637 | var container = document.getElementById(containerId); |
594 | 638 | if (!container) return; |
595 | 639 | if (!data.patterns || data.patterns.length === 0) { |
596 | | - container.innerHTML = "<em style='color:#8b949e'>No parameter patterns captured. Enable <code>capture_params</code> in config.</em>"; |
| 640 | + if (paramsCaptureDisabled()) { |
| 641 | + container.innerHTML = "<em style='color:#8b949e'>Parameter capture is disabled. Enable <code>metrics.capture_params: true</code> in Web UI config.</em>"; |
| 642 | + } else { |
| 643 | + container.innerHTML = "<em style='color:#8b949e'>No parameter patterns captured yet.</em>"; |
| 644 | + } |
597 | 645 | return; |
598 | 646 | } |
599 | 647 | var html = "<table class='param-patterns-table'><thead><tr><th>Parameter Keys</th><th>Count</th></tr></thead><tbody>"; |
|
613 | 661 | updateKPIs(data.summary); |
614 | 662 | updateToolCharts(data.summary.tool_counts); |
615 | 663 | updateErrorBreakdownChart(data.summary.error_counts_by_code || {}); |
616 | | - updateLatencyTable(data.summary.tool_latency); |
| 664 | + latestToolLatencySummary = data.summary.tool_latency || {}; |
| 665 | + updateLatencyTable(latestToolLatencySummary); |
617 | 666 | updateTimeline(data.timeseries); |
618 | 667 | updateLatencyChart(data.timeseries); |
619 | 668 | if (data.sessions !== undefined) { |
|
888 | 937 | el("latency-table").addEventListener("click", function (e) { |
889 | 938 | var btn = e.target.closest(".param-toggle-btn"); |
890 | 939 | if (!btn) return; |
| 940 | + if (btn.disabled || btn.getAttribute("aria-disabled") === "true") return; |
891 | 941 | var targetId = btn.getAttribute("data-target"); |
892 | 942 | var toolName = btn.getAttribute("data-tool"); |
893 | 943 | var detailRow = document.getElementById(targetId); |
|
1079 | 1129 | window.addEventListener("resize", updateDoughnutLegendLayout); |
1080 | 1130 | setupEventHandlers(); |
1081 | 1131 | initKeyboardShortcuts(); |
| 1132 | + loadDashboardConfig(); |
1082 | 1133 | connectWebSocket(); |
1083 | 1134 | startPolling(); |
1084 | 1135 | loadAuditLogs(); |
|
0 commit comments