Spaces:
Sleeping
Sleeping
| // file: error_observer_v16.js | |
| // V16: Comprehensive Error Observer | |
| // Captures JS errors, Promise rejections, Resource failures, Console errors | |
| (() => { | |
| if (window.__ERROR_V16_INSTALLED__) return; | |
| window.__ERROR_V16_INSTALLED__ = true; | |
| // --- CONFIG --- | |
| const MAX_STACK_LENGTH = 1000; | |
| const MAX_MESSAGE_LENGTH = 500; | |
| const CAPTURE_CONSOLE_ERRORS = true; // Set false to disable console.error capture | |
| // --- UTILS --- | |
| function emit(data) { | |
| try { | |
| const payload = JSON.stringify({ ...data, ts: Date.now(), cat: "error" }); | |
| if (window.__py_event) window.__py_event("ERROR_EVT:" + payload); | |
| } catch (_) { } | |
| } | |
| function sanitize(str, maxLen = MAX_MESSAGE_LENGTH) { | |
| if (!str) return null; | |
| return String(str).slice(0, maxLen); | |
| } | |
| function parseStackTrace(stack) { | |
| if (!stack) return null; | |
| try { | |
| // Extract file:line:col from stack | |
| const lines = stack.split('\n') | |
| .slice(0, 5) // First 5 frames | |
| .map(line => { | |
| const match = line.match(/\((.+):(\d+):(\d+)\)/); | |
| if (match) { | |
| return { | |
| file: match[1], | |
| line: parseInt(match[2]), | |
| column: parseInt(match[3]) | |
| }; | |
| } | |
| return null; | |
| }) | |
| .filter(Boolean); | |
| return lines.length > 0 ? lines : sanitize(stack, MAX_STACK_LENGTH); | |
| } catch (_) { | |
| return sanitize(stack, MAX_STACK_LENGTH); | |
| } | |
| } | |
| // --- 1. JAVASCRIPT ERRORS --- | |
| window.addEventListener('error', (event) => { | |
| // Skip if this is a resource error (will be handled separately) | |
| if (event.target && event.target.tagName) { | |
| return; | |
| } | |
| emit({ | |
| type: 'JS_ERROR', | |
| message: sanitize(event.message), | |
| source: sanitize(event.filename), | |
| line: event.lineno, | |
| column: event.colno, | |
| stack: parseStackTrace(event.error?.stack), | |
| url: window.location.href | |
| }); | |
| }, true); | |
| // --- 2. UNHANDLED PROMISE REJECTIONS --- | |
| window.addEventListener('unhandledrejection', (event) => { | |
| const reason = event.reason; | |
| emit({ | |
| type: 'PROMISE_REJECTION', | |
| reason: sanitize(String(reason)), | |
| stack: parseStackTrace(reason?.stack), | |
| url: window.location.href | |
| }); | |
| }); | |
| // --- 3. RESOURCE LOAD ERRORS --- | |
| window.addEventListener('error', (event) => { | |
| if (event.target && event.target.tagName) { | |
| const target = event.target; | |
| emit({ | |
| type: 'RESOURCE_ERROR', | |
| tag: target.tagName.toLowerCase(), | |
| src: sanitize(target.src || target.href), | |
| url: window.location.href, | |
| // Additional context | |
| id: target.id || null, | |
| className: target.className || null | |
| }); | |
| } | |
| }, true); | |
| // --- 4. CONSOLE ERRORS (Optional) --- | |
| if (CAPTURE_CONSOLE_ERRORS) { | |
| const origConsoleError = console.error; | |
| console.error = function (...args) { | |
| // Only capture if not already an Error object being logged | |
| // (to avoid duplicates with JS_ERROR) | |
| const isErrorObject = args.length === 1 && args[0] instanceof Error; | |
| if (!isErrorObject) { | |
| emit({ | |
| type: 'CONSOLE_ERROR', | |
| args: args.map(a => sanitize(String(a))), | |
| url: window.location.href | |
| }); | |
| } | |
| // Call original | |
| origConsoleError.apply(console, args); | |
| }; | |
| // Also capture console.warn for completeness | |
| const origConsoleWarn = console.warn; | |
| console.warn = function (...args) { | |
| emit({ | |
| type: 'CONSOLE_WARN', | |
| args: args.map(a => sanitize(String(a))), | |
| url: window.location.href | |
| }); | |
| origConsoleWarn.apply(console, args); | |
| }; | |
| } | |
| // --- 5. GLOBAL ERROR COUNT (for Network Observer V5 health) --- | |
| // Share error count with network observer for health monitoring | |
| if (!window.__WCS_ERROR_COUNT__) { | |
| window.__WCS_ERROR_COUNT__ = 0; | |
| } | |
| const incrementErrorCount = () => { | |
| window.__WCS_ERROR_COUNT__++; | |
| }; | |
| ['error', 'unhandledrejection'].forEach(evt => { | |
| window.addEventListener(evt, incrementErrorCount, true); | |
| }); | |
| console.log("[WCS] Error Observer V16 Active"); | |
| })(); | |