Add structured runtime diagnostics
This commit is contained in:
parent
29a5698fe0
commit
545e94dddc
89
src/diagnostics.js
Normal file
89
src/diagnostics.js
Normal file
@ -0,0 +1,89 @@
|
||||
const MAX_LOG_ENTRIES = 300;
|
||||
const logBuffer = [];
|
||||
let snapshotProvider = null;
|
||||
let browserDiagnosticsInstalled = false;
|
||||
|
||||
const safeError = (error) => {
|
||||
if (!error) return null;
|
||||
if (error instanceof Error) {
|
||||
return {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
stack: error.stack || null,
|
||||
};
|
||||
}
|
||||
return { message: String(error) };
|
||||
};
|
||||
|
||||
const trimLogs = () => {
|
||||
if (logBuffer.length > MAX_LOG_ENTRIES) {
|
||||
logBuffer.splice(0, logBuffer.length - MAX_LOG_ENTRIES);
|
||||
}
|
||||
};
|
||||
|
||||
export const airshipLog = (event, data = {}, level = 'info') => {
|
||||
const entry = {
|
||||
ts: new Date().toISOString(),
|
||||
level,
|
||||
event,
|
||||
...data,
|
||||
};
|
||||
|
||||
logBuffer.push(entry);
|
||||
trimLogs();
|
||||
|
||||
const method = level === 'error' ? 'error' : level === 'warn' ? 'warn' : 'log';
|
||||
console[method]('[airship]', event, entry);
|
||||
return entry;
|
||||
};
|
||||
|
||||
export const registerDebugSnapshot = (provider) => {
|
||||
snapshotProvider = typeof provider === 'function' ? provider : null;
|
||||
};
|
||||
|
||||
export const getAirshipLogs = () => logBuffer.map((entry) => ({ ...entry }));
|
||||
|
||||
export const clearAirshipLogs = () => {
|
||||
logBuffer.length = 0;
|
||||
};
|
||||
|
||||
export const installBrowserDiagnostics = () => {
|
||||
if (typeof window === 'undefined' || browserDiagnosticsInstalled) return;
|
||||
browserDiagnosticsInstalled = true;
|
||||
|
||||
window.__AIRSHIP_LOGS__ = logBuffer;
|
||||
window.airshipDebug = {
|
||||
getLogs: getAirshipLogs,
|
||||
clearLogs: clearAirshipLogs,
|
||||
snapshot: () => {
|
||||
try {
|
||||
return snapshotProvider?.() ?? null;
|
||||
} catch (error) {
|
||||
airshipLog('debug:snapshot-error', { error: safeError(error) }, 'error');
|
||||
return null;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
window.addEventListener('error', (event) => {
|
||||
airshipLog('runtime:error', {
|
||||
message: event.message || 'Unknown window error',
|
||||
source: event.filename || null,
|
||||
line: event.lineno || null,
|
||||
column: event.colno || null,
|
||||
error: safeError(event.error),
|
||||
}, 'error');
|
||||
});
|
||||
|
||||
window.addEventListener('unhandledrejection', (event) => {
|
||||
airshipLog('runtime:unhandled-rejection', {
|
||||
error: safeError(event.reason),
|
||||
}, 'error');
|
||||
});
|
||||
|
||||
airshipLog('diagnostics:installed', {
|
||||
userAgent: navigator?.userAgent || 'unknown',
|
||||
});
|
||||
};
|
||||
|
||||
installBrowserDiagnostics();
|
||||
Loading…
x
Reference in New Issue
Block a user