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