|
567 | 567 | html += `<div class="empty" style="margin-top:24px;color:var(--green)">✓ All systems nominal. No stalls, zombies, or dispatch failures detected.</div>`; |
568 | 568 | } |
569 | 569 |
|
| 570 | + // ── Debug Log — system snapshot for AI analysis ── |
| 571 | + html += `<div class="nav-separator" style="margin:32px 0 16px"></div>`; |
| 572 | + html += `<div class="section-header"><span class="section-title">📋 Debug Log — System Snapshot</span></div>`; |
| 573 | + html += `<div class="card-sub" style="margin-bottom:12px"> |
| 574 | + Generate a plain-text snapshot of the entire system state. Copy and paste into an AI tool for error analysis. |
| 575 | + </div>`; |
| 576 | + html += `<div class="debug-log-toolbar"> |
| 577 | + <div style="display:flex;gap:6px"> |
| 578 | + <button class="btn ${window.__debugMinutes === 2 ? 'active' : ''}" onclick="window.__loadDebugLog(2)">Last 2 min</button> |
| 579 | + <button class="btn ${window.__debugMinutes === 5 || !window.__debugMinutes ? 'active' : ''}" onclick="window.__loadDebugLog(5)">Last 5 min</button> |
| 580 | + <button class="btn ${window.__debugMinutes === 10 ? 'active' : ''}" onclick="window.__loadDebugLog(10)">Last 10 min</button> |
| 581 | + </div> |
| 582 | + <button class="btn" onclick="window.__copyDebugLog()" id="copyDebugBtn" style="display:${window.__debugLogText ? 'inline-flex' : 'none'}">📋 Copy to Clipboard</button> |
| 583 | + </div>`; |
| 584 | + |
| 585 | + if (window.__debugLogText) { |
| 586 | + html += `<pre class="debug-log-viewer" id="debugLogContent">${esc(window.__debugLogText)}</pre>`; |
| 587 | + } else if (window.__debugLoading) { |
| 588 | + html += `<div class="debug-log-viewer" style="text-align:center;padding:40px;color:var(--text-muted)">Loading snapshot…</div>`; |
| 589 | + } else { |
| 590 | + html += `<div class="debug-log-viewer" style="text-align:center;padding:40px;color:var(--text-muted)">Click a time window button above to generate a snapshot</div>`; |
| 591 | + } |
| 592 | + |
570 | 593 | return html; |
571 | 594 | }, |
572 | 595 |
|
|
846 | 869 | window.__dbSetOffset = (o) => { window.__dbOffset = o; navigate(); }; |
847 | 870 | window.__switchDbTable = (t) => { window.__dbTable = t; window.__dbOffset = 0; navigate(); }; |
848 | 871 |
|
| 872 | + // ─── Debug Log State ──────────────────────────────── |
| 873 | + window.__debugLogText = ""; |
| 874 | + window.__debugMinutes = 0; |
| 875 | + window.__debugLoading = false; |
| 876 | + |
| 877 | + window.__loadDebugLog = async (minutes) => { |
| 878 | + window.__debugMinutes = minutes; |
| 879 | + window.__debugLoading = true; |
| 880 | + window.__debugLogText = ""; |
| 881 | + navigate(); // re-render to show loading state |
| 882 | + try { |
| 883 | + const resp = await fetch(`/api/diagnostics/snapshot?minutes=${minutes}`); |
| 884 | + window.__debugLogText = await resp.text(); |
| 885 | + } catch (err) { |
| 886 | + window.__debugLogText = `Error loading snapshot: ${err.message}`; |
| 887 | + } |
| 888 | + window.__debugLoading = false; |
| 889 | + navigate(); // re-render with content |
| 890 | + }; |
| 891 | + |
| 892 | + window.__copyDebugLog = async () => { |
| 893 | + try { |
| 894 | + await navigator.clipboard.writeText(window.__debugLogText); |
| 895 | + const btn = document.getElementById("copyDebugBtn"); |
| 896 | + if (btn) { |
| 897 | + btn.textContent = "✓ Copied!"; |
| 898 | + setTimeout(() => { btn.textContent = "📋 Copy to Clipboard"; }, 2000); |
| 899 | + } |
| 900 | + } catch { |
| 901 | + // Fallback for older browsers |
| 902 | + const ta = document.createElement("textarea"); |
| 903 | + ta.value = window.__debugLogText; |
| 904 | + document.body.appendChild(ta); |
| 905 | + ta.select(); |
| 906 | + document.execCommand("copy"); |
| 907 | + document.body.removeChild(ta); |
| 908 | + const btn = document.getElementById("copyDebugBtn"); |
| 909 | + if (btn) { |
| 910 | + btn.textContent = "✓ Copied!"; |
| 911 | + setTimeout(() => { btn.textContent = "📋 Copy to Clipboard"; }, 2000); |
| 912 | + } |
| 913 | + } |
| 914 | + }; |
| 915 | + |
849 | 916 | // ─── Router ───────────────────────────────────────── |
850 | 917 |
|
851 | 918 | function getRoute() { |
|
0 commit comments