Skip to content

Commit a2ae5da

Browse files
committed
Capture console errors; not just unhandled ones
1 parent fa5df76 commit a2ae5da

File tree

1 file changed

+40
-30
lines changed

1 file changed

+40
-30
lines changed

front_end/core/host/RNPerfMetrics.ts

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export function getInstance(): RNPerfMetrics {
2020

2121
type UnsubscribeFn = () => void;
2222
class RNPerfMetrics {
23+
readonly #CONSOLE_ERROR_METHOD = 'error';
2324
#listeners: Set<RNReliabilityEventListener> = new Set();
2425
#launchId: string|null = null;
2526

@@ -70,33 +71,33 @@ class RNPerfMetrics {
7071
}
7172

7273
registerGlobalErrorReporting(): void {
73-
window.addEventListener('error', event => {
74-
this.sendEvent({
75-
eventName: 'Browser.UnhandledError',
76-
params: {
77-
type: 'error',
78-
message: event.message,
79-
error: event.error instanceof Error ? event.error : null,
80-
}
81-
});
82-
}, {passive: true});
83-
84-
window.addEventListener('unhandledrejection', event => {
85-
let message: string;
74+
// Indirection for `console` ensures minifier won't strip this out.
75+
const cons = globalThis.console;
76+
const originalConsoleError = cons[this.#CONSOLE_ERROR_METHOD];
77+
cons[this.#CONSOLE_ERROR_METHOD] = (...args: unknown[]) => {
8678
try {
87-
message = String(event.reason);
88-
} catch {
89-
message = '[Promise was rejected without a serialisable reason]';
79+
const maybeError = args[0];
80+
const [message, error] = maybeWrapError('[RNPerfMetrics] console.error called', maybeError);
81+
this.sendEvent({
82+
eventName: 'Browser.ConsoleError',
83+
params: {
84+
message,
85+
error,
86+
}
87+
});
88+
} catch (e) {
89+
const [message, error] = maybeWrapError('[RNPerfMetrics] Error handling console.error', e);
90+
this.sendEvent({
91+
eventName: 'Browser.ConsoleError',
92+
params: {
93+
message,
94+
error,
95+
}
96+
});
97+
} finally {
98+
originalConsoleError.apply(cons, args);
9099
}
91-
this.sendEvent({
92-
eventName: 'Browser.UnhandledError',
93-
params: {
94-
type: 'rejectedPromise',
95-
message,
96-
error: event.reason instanceof Error ? event.reason : null,
97-
}
98-
});
99-
}, {passive: true});
100+
}
100101
}
101102

102103
setLaunchId(launchId: string|null): void {
@@ -175,6 +176,16 @@ function maybeTruncateDeveloperResourceUrl(parsedURL: ParsedURL): string {
175176
return parsedURL.isHttpOrHttps() ? url : `${url.slice(0, 100)} …(omitted ${url.length - 100} characters)`;
176177
}
177178

179+
function maybeWrapError(baseMessage: string, error: unknown): [string, Error] {
180+
if (error instanceof Error) {
181+
const message = `${baseMessage}: ${error.message}`
182+
return [message, error];
183+
}
184+
185+
const message = `${baseMessage}: ${String(error)}`;
186+
return [message, new Error(message, {cause: error})];
187+
}
188+
178189
type CommonEventFields = Readonly<{
179190
timestamp: DOMHighResTimeStamp,
180191
launchId: string | void | null,
@@ -203,12 +214,11 @@ export type BrowserVisibilityChangeEvent = Readonly<{
203214
}>,
204215
}>;
205216

206-
export type UnhandledErrorEvent = Readonly<{
207-
eventName: 'Browser.UnhandledError',
217+
export type ConsoleErrorEvent = Readonly<{
218+
eventName: 'Browser.ConsoleError',
208219
params: Readonly<{
209-
type: 'error' | 'rejectedPromise',
210220
message: string,
211-
error: Error | null | undefined,
221+
error: Error,
212222
}>,
213223
}>;
214224

@@ -238,7 +248,7 @@ export type DeveloperResourceLoadingFinishedEvent = Readonly<{
238248
}>;
239249

240250
export type ReactNativeChromeDevToolsEvent = EntrypointLoadingStartedEvent|EntrypointLoadingFinishedEvent|
241-
DebuggerReadyEvent|BrowserVisibilityChangeEvent|UnhandledErrorEvent|RemoteDebuggingTerminatedEvent|
251+
DebuggerReadyEvent|BrowserVisibilityChangeEvent|ConsoleErrorEvent|RemoteDebuggingTerminatedEvent|
242252
DeveloperResourceLoadingStartedEvent|DeveloperResourceLoadingFinishedEvent;
243253

244254
export type DecoratedReactNativeChromeDevToolsEvent = CommonEventFields&ReactNativeChromeDevToolsEvent;

0 commit comments

Comments
 (0)