背景
我们的项目通过重写console
对象上的方法实现日志上报的功能,截取代码片段如下:
Class Logger() {
debug() {},
info() {},
warn() {},
...
}
const logger = new Logger();
logger.hook = function(target) {
['debug','info','warn','error'].forEach(key => {
const old = target[key];
target[key] = function(...args) {
old && old(...args);
logger[key](...args);
};
});
};
logger.hook(console);
然而在极少部分手机(iPhone 5s 9.3.1)中,在页面上使用console
打印内容,会导致页面渲染失败,也不会向后台发送任何内容。
fixed
经过排查,发现问题出现在old && old(...args)
。由于我们重写了console
对象上的方法,导致执行console.warn()
等方法时,丢失了对应的上下文。需更改为:
old && old.call(target, ...args);
有感而发
经过排查,简单的一句话带过了这次排错的过程。但实际上,这次的排查过程却花费了一天的时间。现在回想起来,大量的时间都是无效、徒劳的。回放...
这是一个上线比较久的项目,最近也没有更新版本。
6.28 有用户反馈首页打开空白,弹窗提示“抱歉,我们出现了一点问题”。我立即用我的手机进行测试,bug 复现。
第一步:查看日志
由于是线上问题,第一反应就是查看错误日志,然而系统中并没有发现对应的内容。接着审查了页面的代码,没有改动也没有发现明显的问题。
第二步:查看灰度环境
在我们的项目中,灰度和正式环境的代码几乎一样,所以我测试了下灰度环境,页面可以正常打开。
第三步:本地打开正式环境
此时我怀疑是灰度环境和正式环境的代码不一致,于是切换到主分支,在本地环境上跑一遍,不幸的是,页面依然可以正常打开。
第四步:同步灰度、正式环境代码
删除了灰度环境的代码,部署了一份和正式环境相同的代码,页面打开空白,弹窗提示“抱歉,我们出现了一点问题”。
第五步:“调试”线上代码
经历了上面的步骤,我的内心是崩溃的。
这时我们想要明确的知道详细的错误内容,于是改造代码,借助弹窗来帮助我们显示错误内容。由于思虑不周,得到的信息都不够详细。在经历了一系列的更改-发布-上线后,我们终于定位到错误在代码中的位置了。
遗憾的是,这个位置的代码并没有错误。
第六步:删除 console
再再再再次调试源代码,删除无关的内容,终于定位到真正的错误位置。
还有一些过程没有写出来,比如在线上环境中加eruda
,却发现页面又正常打开了等诸多因素干扰了我们的判断。但归根结底,还是排查方法不当。
试着总结
对于线上代码的报错,首先查看错误日志,找到错误在源码中的位置。
如果日志并不能提供有效的信息,此时,应在本地切换到主分支,并模拟线上环境进行调试。
然后,使用删除大法,定位错误源。
祝安~