Fix extracting errors from console.error data

Summary: Flipper logs all errors reported by "console.error", but I found that stack traces are broken for them. It is because a bug in `extractError` function which extracts errors from the data logged to console. It fails to extract original error stack trace and instead always logs stack trace where "console.error" was called.  This diff fixes the issue, so errors are properly reported with their original stack traces. However, sometimes stack trace of console.error call can also be useful to find where the error was actually catched and logged, so we're now writing this stack trace into addition field "log_stack_trace".

Reviewed By: passy

Differential Revision: D28466569

fbshipit-source-id: 55fb8ab52c05e8196efc1e47aec95cc1fbc0e594
This commit is contained in:
Anton Nikolaev
2021-05-18 08:06:07 -07:00
committed by Facebook GitHub Bot
parent 8bbf9c46a3
commit 03a1add092
3 changed files with 31 additions and 6 deletions

View File

@@ -8,7 +8,10 @@
*/
import {Store} from '../../reducers/index';
import {getStringFromErrorLike} from '../../utils/errors';
import {
getErrorFromErrorLike,
getStringFromErrorLike,
} from '../../utils/errors';
import {Args, Logger} from '../../fb-interfaces/Logger';
const instance = {
@@ -24,8 +27,8 @@ export function extractError(...data: Array<any>): {
message: string;
error: Error;
} {
const message = data.map(getStringFromErrorLike).join(' ');
const error = data.find((e) => e instanceof Error) || new Error(message);
const message = getStringFromErrorLike(data);
const error = getErrorFromErrorLike(data) ?? new Error(message);
return {
message,
error,

View File

@@ -14,12 +14,34 @@ export class CancelledPromiseError extends Error {
}
}
export function isError(obj: any): obj is Error {
return (
obj instanceof Error ||
(obj.name &&
typeof obj.name === 'string' &&
obj.message &&
typeof obj.message === 'string' &&
obj.stack &&
typeof obj.stack === 'string')
);
}
export function getErrorFromErrorLike(e: any): Error | undefined {
if (Array.isArray(e)) {
return e.map(getErrorFromErrorLike).find((x) => x);
} else if (isError(e)) {
return e;
} else {
return undefined;
}
}
export function getStringFromErrorLike(e: any): string {
if (Array.isArray(e)) {
return e.map(getStringFromErrorLike).join(' ');
} else if (typeof e == 'string') {
return e;
} else if (e instanceof Error) {
} else if (isError(e)) {
return e.message || e.toString();
} else {
try {

View File

@@ -8,7 +8,7 @@
*/
import {getInstance} from '../fb-stubs/Logger';
import {CancelledPromiseError} from './errors';
import {CancelledPromiseError, isError} from './errors';
type Result =
| {kind: 'success'}
@@ -180,7 +180,7 @@ function logPluginSuccessRate(name: string, plugin: string, result: Result) {
}
function extractMessage(error: any) {
if (error instanceof Error) {
if (isError(error)) {
return error.message;
}
return JSON.stringify(error);