[bug]—console 在某些机型下的隐藏坑

背景

我们的项目通过重写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,却发现页面又正常打开了等诸多因素干扰了我们的判断。但归根结底,还是排查方法不当。

试着总结

对于线上代码的报错,首先查看错误日志,找到错误在源码中的位置。

如果日志并不能提供有效的信息,此时,应在本地切换到主分支,并模拟线上环境进行调试。

然后,使用删除大法,定位错误源。

祝安~

posted @ 2019-07-01 15:54 廖飞银 阅读(...) 评论(...) 编辑 收藏