|
475 | 475 | ::-webkit-scrollbar-track { background: transparent; } |
476 | 476 | ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; } |
477 | 477 | </style> |
| 478 | +<script src="https://browser.sentry-cdn.com/9.27.0/bundle.min.js" crossorigin="anonymous"></script> |
| 479 | +<script> |
| 480 | +Sentry.init({ |
| 481 | + dsn: 'https://46ad94b35a51979ba4223eeffe38f5c8@o4511097126780928.ingest.us.sentry.io/4511103122210816', |
| 482 | + environment: 'local', |
| 483 | + release: '', |
| 484 | + tracesSampleRate: 1.0, |
| 485 | + initialScope: { tags: { dashboard: 'index' } }, |
| 486 | +}); |
| 487 | +</script> |
478 | 488 | </head> |
479 | 489 | <body> |
480 | 490 | <div class="app"> |
|
766 | 776 | renderInc(); |
767 | 777 | renderStd(); |
768 | 778 | log('health','INFO ','ws_connected','WebSocket connected to plugin at ' + url); |
| 779 | + if (typeof Sentry !== 'undefined') { |
| 780 | + Sentry.addBreadcrumb({ category: 'ws', message: 'WebSocket connected', level: 'info' }); |
| 781 | + Sentry.setTag('ws_connected', true); |
| 782 | + } |
769 | 783 | }; |
770 | 784 | ws.onclose = () => { |
771 | 785 | ws = null; mockPaused = false; |
772 | 786 | setWs('disconnected'); |
773 | 787 | log('health','WARN ','ws_closed','Connection lost — retrying in 3 s'); |
| 788 | + if (typeof Sentry !== 'undefined') { |
| 789 | + Sentry.addBreadcrumb({ category: 'ws', message: 'WebSocket disconnected', level: 'warning' }); |
| 790 | + Sentry.setTag('ws_connected', false); |
| 791 | + } |
774 | 792 | setTimeout(connectWs, 3000); |
775 | 793 | }; |
776 | 794 | ws.onerror = () => { ws = null; mockPaused = false; }; |
777 | | - ws.onmessage = e => { try { onMsg(JSON.parse(e.data)); } catch {} }; |
| 795 | + ws.onmessage = e => { |
| 796 | + try { onMsg(JSON.parse(e.data)); } |
| 797 | + catch (err) { if (typeof Sentry !== 'undefined') Sentry.captureException(err); } |
| 798 | + }; |
778 | 799 | } catch { |
779 | 800 | setWs('disconnected'); |
780 | 801 | setTimeout(connectWs, 3000); |
|
789 | 810 |
|
790 | 811 | /** Structured UI telemetry for Loki (plugin → plugin-structured.jsonl; ingestion outside plugin). */ |
791 | 812 | function sendDashboardUiEvent({ element_id, event_type, message, value }) { |
| 813 | + if (typeof Sentry !== 'undefined') { |
| 814 | + Sentry.addBreadcrumb({ |
| 815 | + category: 'ui.' + event_type, |
| 816 | + message: message, |
| 817 | + data: { element_id }, |
| 818 | + level: 'info', |
| 819 | + }); |
| 820 | + } |
792 | 821 | if (!ws || ws.readyState !== WebSocket.OPEN) return false; |
793 | 822 | const o = { action: 'log', event: 'dashboard_ui_event', element_id, event_type, message }; |
794 | 823 | if (value !== undefined && value !== null) o.value = value; |
|
829 | 858 | const pv = m.pluginVersion ? String(m.pluginVersion) : ''; |
830 | 859 | pvEl.textContent = pv ? ('v' + pv) : 'v—'; |
831 | 860 | pvEl.title = pv ? ('Sim Steward plugin ' + pv) : 'Sim Steward plugin build'; |
| 861 | + if (pv && typeof Sentry !== 'undefined') { |
| 862 | + const client = Sentry.getClient(); |
| 863 | + if (client && client.getOptions) client.getOptions().release = pv; |
| 864 | + Sentry.setTag('plugin_version', pv); |
| 865 | + } |
832 | 866 | } |
833 | 867 | const pill = document.getElementById('mode-pill'); |
834 | 868 | pill.className = 'mode-pill ' + (mode==='Replay'?'replay':'waiting'); |
|
0 commit comments