fix(mobile): record xprem_js_crash only for fatal JS errors

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jjbruntonandClaude Fable 5 committed 2026-08-31 11:13:55 +01:00
1 parent 659cee76b6
commit 5c4a4608b1
2 files changed
+29 -12

No files matched your search

+17 -3
View File
@@ -75,12 +75,26 @@ describe('observe', () => {
expect.objectContaining({ expect.objectContaining({
severity: 'fatal', severity: 'fatal',
body: 'boom', body: 'boom',
attributes: { isFatal: true },
}) })
); );
expect(previousHandler).toHaveBeenCalledWith(error, true); expect(previousHandler).toHaveBeenCalledWith(error, true);
}); });
it('does not log xprem_js_crash for non-fatal errors but still delegates', () => {
const previousHandler = jest.fn();
const getInstalledHandler = installFakeErrorUtils(previousHandler);
withFreshObserveModule(({ installObserveGlobalErrorHandler }) => {
installObserveGlobalErrorHandler();
});
const error = new Error('handled');
getInstalledHandler()(error, false);
expect(logEventMock).not.toHaveBeenCalled();
expect(previousHandler).toHaveBeenCalledWith(error, false);
});
it('still calls the previous handler when Observe.logEvent throws', () => { it('still calls the previous handler when Observe.logEvent throws', () => {
const previousHandler = jest.fn(); const previousHandler = jest.fn();
const getInstalledHandler = installFakeErrorUtils(previousHandler); const getInstalledHandler = installFakeErrorUtils(previousHandler);
@@ -92,8 +106,8 @@ describe('observe', () => {
installObserveGlobalErrorHandler(); installObserveGlobalErrorHandler();
}); });
getInstalledHandler()(new Error('boom'), false); getInstalledHandler()(new Error('boom'), true);
expect(previousHandler).toHaveBeenCalledWith(expect.any(Error), false); expect(previousHandler).toHaveBeenCalledWith(expect.any(Error), true);
}); });
}); });
+12 -9
View File
@@ -50,15 +50,18 @@ export function installObserveGlobalErrorHandler() {
const previousHandler = errorUtils.getGlobalHandler(); const previousHandler = errorUtils.getGlobalHandler();
errorUtils.setGlobalHandler((error, isFatal) => { errorUtils.setGlobalHandler((error, isFatal) => {
try { // Only fatal errors count as a crash; non-fatal handled errors would
const message = error instanceof Error ? error.message : String(error); // otherwise skew update-health tracking.
Observe.logEvent("xprem_js_crash", { if (isFatal) {
severity: "fatal", try {
body: message, const message = error instanceof Error ? error.message : String(error);
attributes: { isFatal: Boolean(isFatal) }, Observe.logEvent("xprem_js_crash", {
}); severity: "fatal",
} catch (observeError) { body: message,
console.warn("[Observe] Failed to log xprem_js_crash:", observeError); });
} catch (observeError) {
console.warn("[Observe] Failed to log xprem_js_crash:", observeError);
}
} }
previousHandler(error, isFatal); previousHandler(error, isFatal);