背景

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

试着总结

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

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

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

祝安~

[bug]—console 在某些机型下的隐藏坑的更多相关文章

  1. Linux下进程隐藏的方法及其对抗

    零.背景 在应急响应中,经常碰到ps命令和top命令查不到恶意进程(异常进程)的情况,会对应急响应造成很大的影响.轻则浪费时间,重则排查不出问题,让黑客逍遥法外.所以这篇博客研究学习如何对抗linux ...

  2. Windows下新建隐藏用户名

    Windows下新建隐藏用户名,防止忘记密码

  3. Springboot 之 自定义配置文件及读取配置文件注意:配置文件中的字符串不要有下划线 .配置中 key不能带下划线,value可以(下划线的坑,坑了我两天..特此纪念)

    注意:配置文件中的字符串不要有下划线 .配置中  key不能带下划线,value可以 错误的.不能读取的例子: mySet .ABAP_AS_POOLED      =  ABAP_AS_WITH_P ...

  4. Faster_Rcnn在windows下运行踩坑总结

    Faster_Rcnn在windows下运行踩坑总结  20190524 今天又是元气满满的一天! 1.代码下载 2.编译 3.下载数据集 4.下载pre-train Model 5.运行train ...

  5. IE下单选按钮隐藏后点击对应label无法选中的bug解决

    项目中,有时候填写表单我们的选项会隐藏掉radio或者checkbox,而只显示给用户对应的文字选择,如果用户点击label选择时,在FF/Chrome等标准浏览器中隐藏掉的radio/checkbo ...

  6. .NET4.5 Console.ReadKey()在多线程下的BUG

    .NET 4.5 在多线程的控制台里,Console.ReadKey()可能会造成线程死锁.看代码: static void Main(string[] args) { System.Timers.T ...

  7. MVVM框架下 WPF隐藏DataGrid一列

    最近的一个项目,需要在部分用户登录的时候,隐藏DataGrid中的一列,但是常规的绑定不好使,在下面举个例子. XAML部分代码 <Window x:Class="DataGridCo ...

  8. IE下设置unselectable与onselectstart属性的bug,Firefox与Chrome下的解决方案

    在IE下给DIV设置unselectable与onselectstart属性,可以让div的内容不能选中,这个功能在很多情况下,非常有用,但是他的bug太明显, 直接使用一个DIV是可以的,比如: & ...

  9. PHPStudy+PHPStorm下配置隐藏项目入口文件

    img { max-width: 100% } 默认情况下项目入口文件是站点根目录下index.php文件,一般程序启动时通过这个文件,定义文件路径,配置重要节点(比如是否开启调试模式),注册路由等, ...

随机推荐

  1. Go语言 - 结构体 | 方法

    自定义类型和类型别名 自定义类型 在Go语言中有一些基本的数据类型,如string.整型.浮点型.布尔等数据类型, Go语言中可以使用type关键字来定义自定义类型. 自定义类型是定义了一个全新的类型 ...

  2. 接口调试工具Postman之自动同步Chrome cookies,实现自动登陆验证

    前言 在前后端分离开发时,做为后端开发人员,要求独立开发完成某个接口后,开发人员自己需要先测试通过后再提交给测试人员进行测试,否则会出现到测试人员哪里业务流程根本就走不通,或者BUG会过多的情况等. ...

  3. SpringBoot整合ActiveMQ发送邮件

    虽然ActiveMQ以被其他MQ所替代,但仍有学习的意义,本文采用邮件发送的例子展示ActiveMQ 1. 生产者1.1 引入maven依赖1.2 application.yml配置1.3 创建配置类 ...

  4. Git常用命令与入门

    Git 仓库就是那个.git 目录,其中存放的是我们所提交的文档索引内容,Git 可基于文档索引内容对其所管理的文档进行内容追踪,从而实现文档的版本控制..git目录位于工作目录内.对于任何一个文件, ...

  5. bzoj1176: [Balkan2007]Mokia cdq

    链接 bzoj 思路 cdq入门题,拆成4个矩阵,然后cdq. 代码 /************************************************************** P ...

  6. 大厂HR面试必备ES6中的深入浅出面试题知识点

    ESMAScript6简介,ES6是JavaScript语言的下一代标准,目的是让JavaScript语言可以写复杂的大型应用程序,成为企业级语言.那么ECMAScript和JavaScript的关系 ...

  7. nginx 访问控制之 document_uri

    这就用到了变量$document_uri,根据前面所学内容,该变量等价于$uri,其实也等价于location匹配. 示例1: if ($document_uri ~ "/admin/&qu ...

  8. ex2

    #include <stdio.h> int main() { int days; printf("输入一个整数: \n"); scanf("%d" ...

  9. MySQL数据库中文乱码问题

    mysql> select * from books; +-----+---------------------------------+---------+-------------+---- ...

  10. LSF 作业系统常用命令

    LSF(Load Sharing Facility)是一个被广泛使用的作业管理系统,具有高吞吐.配置灵活的优点.通过 LSF 集中监控和调度,可以充分利用计算机的CPU.内存.磁盘等资源. bqueu ...