我在一个项目上设置了 Firebase Crashlytics,并且我知道它正在工作(因为它偶尔确实会在正确的文件中显示一些错误)。
我尝试
crashlytics().recordError(err, 'api_error')
(其中 err
是来自 axios 的有效错误子类对象),但在 Firebase 控制台的 Crashlytics 仪表板上看不到它。
但是,它没有反映到仪表板。我已经尝试过好几次了。我究竟做错了什么? (我使用的是 iOS 16.6)
更新:我可以用
crashlytics().crash()
完美地强制崩溃,它会立即显示在仪表板上。好像和recordError
有关系。我也在crashlytics_debug_enabled
中将true
更改为firebase.json
,但没有效果。
更新2:
当我进一步挖掘时,我发现 recordError 内部调用:
StackTrace.fromError(error, { offline: true }).then(stackFrames => {
this.native.recordError(createNativeErrorObj(error, stackFrames, false, jsErrorName));
});
fromError 定义为(在 stacktrace 库中):
fromError: function StackTrace$$fromError(error, opts) {
opts = _merge(_options, opts);
var gps = new StackTraceGPS(opts);
return new Promise(function(resolve) {
var stackframes = _filtered(ErrorStackParser.parse(error), opts.filter);
resolve(Promise.all(stackframes.map(function(sf) {
return new Promise(function(resolve) {
function resolveOriginal() {
resolve(sf);
}
gps.pinpoint(sf).then(resolve, resolveOriginal)['catch'](resolveOriginal);
});
})));
}.bind(this));
},
单步执行断点后,我发现错误源于 _filtered(ErrorStackParser.parse(error), opts.filter);线。错误堆栈解析器。其中的解析方法是(在 error-stack-parser 库中):
parse: function ErrorStackParser$$parse(error) {
if (typeof error.stacktrace !== 'undefined' || typeof error['opera#sourceloc'] !== 'undefined') {
return this.parseOpera(error);
} else if (error.stack && error.stack.match(CHROME_IE_STACK_REGEXP)) {
return this.parseV8OrIE(error);
} else if (error.stack) {
return this.parseFFOrSafari(error);
} else {
throw new Error('Cannot parse given Error object');
}
},
我的axios错误在上面的方法之前都是正确的,但是代码在 throw new Error('Cannot parse给定的Error object');处抛出,一路向上游抛出,因此错误永远无法提交。
(也作为问题提交到仓库https://github.com/invertase/react-native-firebase/issues/7282)
核心问题似乎在于 ErrorStackParser 如何尝试解析 axios 错误。
从您的调试来看:
我的axios错误在上面的方法之前都是正确的,但是代码在 throw new Error('Cannot parse给定的Error object');处抛出,一路向上游抛出,因此错误永远无法提交。
该错误表明 error-stack-parser 无法识别并正确解析 axios 错误的堆栈跟踪格式。
需要考虑的一些潜在解决方案或解决方法:
const standardError = new Error(err.message);
standardError.stack = err.stack;
crashlytics().recordError(standardError, 'api_error');