【穿山甲系列】老司机的千里眼——穿山甲SDK

作者:邓曦

团队:腾讯移动品质中心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,获取更多测试干货!

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨龙飞前端

scrollto 到指定位置

2994
来自专栏Golang语言社区

【Golang语言社区】GO1.9 map并发安全测试

var m sync.Map //全局 func maintest() { // 第一个 YongHuomap := make(map[st...

5548
来自专栏C#

DotNet加密方式解析--非对称加密

    新年新气象,也希望新年可以挣大钱。不管今年年底会不会跟去年一样,满怀抱负却又壮志未酬。(不过没事,我已为各位卜上一卦,卦象显示各位都能挣钱...)...

6068
来自专栏张善友的专栏

LINQ via C# 系列文章

LINQ via C# Recently I am giving a series of talk on LINQ. the name “LINQ via C...

3025
来自专栏张善友的专栏

Mix 10 上的asp.net mvc 2的相关Session

Beyond File | New Company: From Cheesy Sample to Social Platform Scott Hansel...

2787
来自专栏张善友的专栏

Miguel de Icaza 细说 Mix 07大会上的Silverlight和DLR

Mono之父Miguel de Icaza 详细报道微软Mix 07大会上的Silverlight和DLR ,上面还谈到了Mono and Silverligh...

3017
来自专栏我和未来有约会

Silverlight第三方控件专题

这里我收集整理了目前网上silverlight第三方控件的专题,若果有所遗漏请告知我一下。 名称 简介 截图 telerik 商 RadC...

4425
来自专栏一个会写诗的程序员的博客

Spring Reactor 项目核心库Reactor Core

Non-Blocking Reactive Streams Foundation for the JVM both implementing a Reactiv...

2872
来自专栏pangguoming

Spring Boot集成JasperReports生成PDF文档

由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲...

1.5K7
来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

5288

扫码关注云+社区