作者:邓曦

团队:腾讯移动品质中心 TMQ

一、背景

APP 发布后,在用户侧出现的问题统称为 “线上问题”。如果 “线上问题” 出现了:

解决率低

存在时间长

的情况,那么对 APP 的口碑会有很大的负面影响。经过我们对 2016 年上半年手机 QQ 浏览器用户反馈分析,我们发现 “线上问题” 解决的主要困难来自于 “对解决问题的关键信息获取困难”,统计数据如下:

图表——日志获取率和时间

大家可以看到:日志的获取率平均只有 10%,平均一份日志获取时间至少 30 小时。那么有没有办法能够改善这种窘境呢?

二、解决方案

1、SDK 架构

既然方向明确了,我们就来制造这个轮子。通过我们多轮迭代后,我们得到了如下的穿山甲 SDK 系统架构:

图表——穿山甲 SDK 架构

从架构图上,可以看出整个 SDK 分为两条线:以 “日志数据” 作为输入的 “数据线” 和以 “Push Cmd/代码 Cmd” 作为输入的 “控制线”。

这也是常用的系统设计思路,数据和控制分离的最佳实践。

下面将分开介绍。

2、数据线

从 2-2 的穿山甲 SDK 架构图中,我们可以看到 “数据线” 分为如下几个主要模块:

1)数据 API

2)缓存模块

3)安全模块

4)扩展服务

(1)数据 API

数据 API 就是打印日志的接口,和普通 android 打印日志基本一致。例子如下:

Logs.d(TAG, “key1=value1;key2=value2;…”);

在这里我们用了自己 Logs 类而不是 android 默认的 Log。日志的内容,也是通过 key=value 的形式进行连接。这是为了将来对日志的智能分析做的规范性要求。

(2)缓存模块

缓存模块主要对日志写入 SD 卡前,做缓存管理提高性能。分为两个部分:

1)L1 缓存

在 Android 中所有 Log.d 打印的日志首先都会进入 L1 缓存进行排队。等 L1 缓存达到临界值,管理逻辑才会把 L1 缓存中所有内容发送到 L2 缓存。

2)L2 缓存

L2 缓存是比较纯粹的写入缓冲区,负责写入 SD 卡前最后缓存。

至于为什么会有 L1 和 L2 两级缓存结构,我们将在后续讲解详细描述。

(3)安全模块

出于安全的考虑,日志内容需要进行压缩加密存储。这个地方就有一个问题:到底是先压缩在加密,还是先加密在压缩? 其实这和我们采取加密算法也有关系。

大家都知道,普通 Zip 加密算法基于 “滑动窗口”。简而言之,在 “滑动窗口” 中出现的重复词越多,压缩比就越大。经过我们实践发现,很多加密算法加密后,重复的词明显比加密前要少。并且,越短的词在加密后,字符串也越短。

1)DES 加密

针对原始日志,进行 DES 对称加密。但是这样做有个问题,加密和解密都是同一个秘钥 A。秘钥 A 会记录在客户端 SDK 代码中,虽然 SDK 代码经过混淆,但是也有被破解的风险。所以,我们加入了第二层的 RSA 加密。

2)RSA 加密

大家都知道,RSA 非对称加密存在性能问题。为了规避性能损耗,我们只是用 RSA 来对 DES 的秘钥 A 进行加密,而不是对整个日志内容加。我们将 DES 中的秘钥 A 改为一个随机字符串,用 RSA 的公钥加密后,写入日志文件第一行。当日志传到 server 后,读取日志第一行,用 RSA 的私钥解密后,得到 DES 的秘钥 A。在用秘钥 A 对剩下的日志进行解密,就能得到日志原文。

(4)扩展服务

扩展服务包括如下组件:

1)CPU 监控

采集 CPU 占用率,用来监控 APP 中某个 CPU 超过阈值的场景。

2)FPS 监控

采集 FPS 占用率,用来监控 APP 中某个 FPS 超过阈值的场景。

3)MEM 监控

采集 MEM 占用率,用来监控 APP 中某个 MEM 超过阈值的场景。

4)基础信息采集

基础信息包括:机型、固件等软硬件信息。

3、控制线

从 2-2 的穿山甲 SDK 架构图中,我们可以看到 “控制线” 分为如下几个主要模块:

1)Cmd API

2)Cmd 模块

3)基础服务

4)SDK 工具

(1)数据 API

通过代码调用 Logs.upload 就能立即上报日志。如果是通过 Push 通道,则需要符合 SDK 的协议字符串即可。

(2)Cmd 模块

所有对 SDK 的控制操作,都被包装为 CMD 进行。

1)协议解析

通过 Push 的 API 接口,是需要进行协议解析的。例如:命令字符串 c=3&date=20170424,就会被解析为:当前命令是 “上报日志”,日志范围 “2017年4月24日” 的日志。

2)配置管理

对 SDK 固有设置进行云端控制和更新。例如:是否打开错误码上报,是否上报用户反馈日志等。

3)调度器

对所有命令进行统 Task 框架调度管理。

(3)基础服务

1)文件分片

我们的分片策略,是按照文件级别区分的。最早我们没有按照日志级别区分,所有 debug、info、warn、error 都输出在同一个日志文件。这样造成一个后果,如果只是需要 debug 日志,不需要其他级别。那么在终端做日志二次提取,必然浪费 CPU 和内存。所以,直接按照日志级别分片为不同日志文件,将来可以直接只上报 debug 级别日志。

2)淘汰策略

日志根据容量进行循环淘汰,这里需要预估在用户侧每日产生日志总体大小。

(4)SDK 工具

1)ZipUtil

提供压缩打包服务,除了日志文件,还能将其他文件附件也打包上传。

2)UploadUtil

提供 Http 上传能力。

3)Task 回调

提供 Task 回调机制,能在任务成功、失败等场景下实现不同的处理逻辑。

4、方案流程

图表——穿山甲 SDK 解决问题思路

(1)分析埋点

问题发生前埋点:就是在没有发生问题之前,对代码中关键位置进行埋点。例如:异常捕获、DB 信息、函数输入输出、Server 信息、分之条件、File 信息等。

问题发生或埋点:出现了用户反馈后,在补充针对问题现象、相关逻辑、排除逻辑等代码位置进行埋点。

(2)数据收集

数据收集,利用 “众测”(公测和正式版不收集),收集用户数据。这里收集标准有:错误码触发和用户主反馈。错误码触发:当一些已知问题发生时,收集程序日志进行上报。用户主动反馈:用户点击反馈论坛进行提交时,收集程序日志进行上报。

(3)数据分析

在数据分析过程中,采用正则表达式提取,针对同一类型日志关键信息进行提取。然后通过离群数据分析,找到 “小众” 部分数据,进行人工分析。

(4)问题解决

通过日志分析出根本原因,开发进行问题修改解决。

(5)线上验证

通过反馈平台和日志上报,验证问题修复后,线上用户验证是否已经 OK。

三、实践效果

1、外部反馈数据

(1)反馈日志获取时间缩短 80%。

以往获取一份用户反馈日志,平均需要 30 小时。采用 SDK 后,平均日志获取时间缩短为 6 小时不到。

(2)浏览器 7 类问题,比预期提前一个版本解决。

小说语音暂停、小说翻页翻不了、小说下载失败等问题比预期提前一个版本解决。

(3)广告过滤类问题,每条处理时间缩短 3 天,缩短 59%。

之前广告过滤,联系用户效率特别低。通过穿山甲 SDK 把广告 URL 直接上传,大大节省了联系用户找到 URL 的时间。

2、内部反馈处理

大家都知道,来自内部的产品反馈,特别是老板的反馈,很难处理。究其原因:

老板记不清复现路径

老板手机不能借给你

按照之前经验,项目组只能按照 “抓瞎” 方式进行问题解决。平均每个问题至少需要一周时间,还必须厚着脸皮去 “骚扰” 老板才行。

现在我们有个穿山甲 SDK,只需要让老板直接用。出了问题,一键上报日志即可,开发拿到日志后 30 分钟就能解决问题。节约研发流程时间 5 天/问题,效益非常明显。

3、H5 游戏问题

(1)背景

图表——H5 游戏打不开背景

有用户反馈,部分 H5 游戏无法进入,严重影响他们的游戏体验。也严重影响了 H5 游戏口碑。

(2)定位和解决

图表 ——H5 游戏打不开 - 定位问题

针对 H5 游戏打不开时,用户网络状态进行埋点。我们通过 “众测” 发现:

1)排除网络原因

94% 用户在 H5 游戏打不开的时候外部网络是通畅的,初步排除网络原因造成。

2)排除机型原因

对打不开的机型进行归类,通过本地无法复现,初步排除机型问题。

最后我们把目标定位到 CP 服务质量,也就是 H5 游戏服务器质量上。最后发现,由于大部分 CP 为了节约成本,没有把 H5 资源放在 CDN 服务器上,导致拉取失败概率增加。通过和 CP 沟通后解决了这个问题。

四、总结

(1)需求阶段

在需求评审阶段,测试人员可以开发约定必要的事前埋点。为提前发现问题做好准备。

(2)编码阶段

这个阶段测试人员,可以和开发人员结对编程,添加主要事前埋点。为接下来解决集成测试中问题,奠定良好的基础。

(3)众测

产品发布 “众测” 后,测试人员可以针对线上出现问题,添加解决问题事后埋点。精准的解决特定问题。

根据我们经验,良好的事前埋点,不仅能够解决线上问题。对于研发流程中问题解决,也能起到巨大的作用。结合穿山甲 SDK 的日志上报能力,为传统测试模式打开了一个新的方向与未来。

关注微信公众号:腾讯移动品质中心 TMQ,获取更多测试干货!


↙↙↙阅读原文可查看相关链接,并与作者交流