记录自己写的线上bug

给NSDictionary设置nil值导致线上崩溃

崩溃描述

这个问题是昨天新版本上线后firebase开始报的,当时正在扫线上的崩溃问题(因为老板注意到我们的崩溃率比其他产品线高很多),所以在崩溃刚出现时就发现了。崩溃原因并不复杂,以下是出现崩溃的代码片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- (void)p_recordMetrics:(NSURLSessionTaskMetrics *)metrics{
if (metrics.transactionMetrics > 0) {
NSMutableDictionary * track = [NSMutableDictionary dictionary];
NSURLSessionTaskTransactionMetrics *tm = metrics.transactionMetrics.lastObject;
[track setObject:@(metrics.taskInterval.duration * 1000) forKey:@"duration"];
[track setObject:tm.request.URL.absoluteString forKey:@"uri"];
NSTimeInterval domain = [tm.domainLookupEndDate timeIntervalSinceDate:tm.domainLookupStartDate] * 1000;
NSTimeInterval connect = [tm.connectEndDate timeIntervalSinceDate:tm.connectStartDate] * 1000;
NSTimeInterval tls = [tm.secureConnectionEndDate timeIntervalSinceDate:tm.secureConnectionStartDate] * 1000;
NSTimeInterval request = [tm.requestEndDate timeIntervalSinceDate:tm.requestStartDate] * 1000;
NSTimeInterval response = [tm.responseEndDate timeIntervalSinceDate:tm.responseStartDate] * 1000;
NSString *str = [NSString stringWithFormat:@"dns:%f,connect:%f,tls:%f,request:%f,response:%f",domain,connect,tls,request,response];
[track setObject:str forKey:@"metrics"];
[[FMBMonitor shareManager] trackData:track type:FMBMonitorTrackerTypeAPISample];
}
}

崩溃发生在给track设置uri的时候,在iOS13上,这个tm.request.URL.absoluteString字段有可能为nil,其他版本下暂时未发现崩溃。

造成的影响

线上的崩溃数增加了一倍,又提高了整体崩溃率。。。

解决过程

发现问题后,马上对代码进行了修改,增加了非空的判断,本来准备跟下个版本一起发,后来发现崩溃数增长有点快,受影响用户会比较多,所以临时发了个bugfix版本。

槽点

万万想不到啊,这个字段居然可能为空,那这个tm的意义何在,就算我拿到下面的耗时数据了也没有任何用啊。

而且只在13上出现这个问题,果然是bugOS啊。。。

经验教训

以后再给字典赋值时,只要不是基本数据类型,一律进行为空判断,管你是从哪里搞的数据,这个社会除了自己,谁也靠不住啊。

使用高版本的api导致线上崩溃

崩溃描述

这个崩溃是之前做开屏广告时写的一个崩溃,当时是重构之前的代码,在新增计时器时为了图方便,用了个iOS10以后的api,当时开发环境都是10以上的设备,所以没有发现问题。

造成的影响

每天新增几千个崩溃。。。

解决过程

发版后第二天才发现问题,然后马上替换了api,发了bugfix版本。

槽点

这个完全是自己的锅。

经验教训

以后在使用系统api,特别是一个api簇的时候,一定要注意api版本兼容性。

代码重构导致api参数丢失的bug

bug描述

在做用户间送礼功能时,对之前的送礼模块进行了一些重构,将一些重复的代码块进行了封装,提炼出了一些公用的函数,在函数提炼过程中,将之前上下文使用到的数据以参数的形式做了传递,其中有一个函数在传参过程中出现了错误,传了初始数据,导致将处理后的数据丢失了。

造成的影响

由于将收礼人的id丢失了,服务器无法统计当前直播间的收礼情况,导致运营的活动无法正常进行,只能临时换活动方案。

解决过程

这个问题很快就定位到并解决了,刚好跟最新的一个版本发布。

槽点

这已经不是第一次在重构过程中出现线上bug了,如何保证重构代码的正确性我可能需要做一些总结了。
快速的业务迭代和对代码质量的严格要求之间确实存在一个博弈和取舍的问题。当然这也和目前项目人手不足有关系,希望新同学的加入能使现状有所缓解,这样我也有更多的时间和精力去做那些一直想做也是真正对项目有帮助的事情。

经验教训

  • 对重构后的代码块一定要进行覆盖测试

  • 在代码重构过程,特别是函数提炼过程中,一定要注意被提炼的这些代码块在之前的上下文中所使用到的数据,保证传参的正确性

  • 代码重构过程,切记不能偷懒,还是得按重构的标准步骤来,慢工出细活不是没有道理