iOS 无埋点方案探究

引言

随着互联网的发展,数据分析的重要性不言而喻,而数据分析依赖全面和精确的数据埋点。如果埋点不够全面或是不够精确,将导致后面的数据分析毫无意义。

1. 背景

埋点分为客户端埋点(前端埋点)和服务端埋点(后端埋点),关于后端埋点这里不做展开描述。本文介绍的 iOS 埋点属于客户端埋点,客户端埋点一般是针对用户操作进行上报,如用户的点击操作,页面路径等。传统的代码埋点对代码侵入非常大,和代码耦合非常高,随着需求的改变,代码和埋点都要进行调整。基于此,无埋点方案应用而生。

2. iOS 埋点方案介绍

iOS 埋点方案主要可以分为三种:

2.1 代码埋点

概念
代码埋点就是在代码里需要上报的地方添加上报的代码。

优点

  • 开发简单。
  • 可以精确的控制上报的事件和时机。
  • 方便地把自定义的事件和详细的参数上报。

缺点

  • 对代码侵入比较大。
  • 埋点工作量大,必须是技术开发人员完成。
  • 更新或新增埋点成本较高,如果遇到漏埋或者需要新埋的点,需要重新发版。

2.2 可视化埋点

概念
可视化埋点是用可视化的方式,提前把需要采集的控件事件进行圈选,并下发给客户端,用户进行操作时,埋点SDK会自动根据下发的配置进行上报,不需要进行代码埋点。

Mixpanel 提供了可视化埋点的方案,并且把代码进行了开源。SensorsData 参考了 Mixpanel,也进行了开源。本文介绍的技术方案方案参考了这两个开源框架。

优点

  • 解决了代码埋点的侵入性、工作量和发版成本问题。

缺点

  • 不是所有的事件都可以圈选埋点,比如一些和业务逻辑耦合比较紧的事件埋点。
  • 无法在埋点时增加自定义的字段。

2.3 无埋点

概念
无埋点最早是在2013年被Heap Analytics等公司提出。无埋点就是把所有的控件操作全部由埋点SDK自动收集,所以也被称为“全埋点”。无埋点和可视化埋点非常相似,区别是可视化埋点是先进行圈选再上报,也就是只上报圈选配置的事件;无埋点是先上报用户操作,再在服务端进行圈选分析。

优点

  • 在可视化埋点的基础上,可以分析已经上报的数据。也就是如果哪天突然想对某个用户操作进行分析,历史数据也可以分析。

缺点

  • 不是所有的事件都可以圈选埋点,比如一些和业务逻辑耦合比较紧的事件埋点。
  • 无法在埋点时增加自定义的字段。
  • 此外因为上报了所有的用户的操作,相比可视化埋点网络负担稍微增大。

3. 无埋点关键技术

由于可视化埋点和无埋点核心技术点相同,可视化埋点也可以看做无埋点的一种方式。下面主要介绍几个这两种埋点方案的核心技术解决方案。

  1. 如何不侵入业务代码自动进行用户操作的收集。
  2. 事件的唯一标识(即 ID) 如何确定。
  3. 圈选如何实现。

3.1 如何不侵入代码自动进行收集

3.1.1 AOP

这里提到一个重要的概念 AOP,AOP 是 Aspect Oriented Programming 的缩写,意为面向切面编程。AOP 是一种编程思想,和 OOP(面向对象编程) 非常相似。AOP 是对业务处理过程中的切面进行提取,在统一的地方进行处理,可以降低各个逻辑部分之间的耦合。

我们根据下面的两张图来直观地体会下 AOP 。

从图中我们可以看出,如果我们要在不同的地方执行一些不同的操作,但都会在操作前的某一个时机做相同的动作(如用户验证,日志打印,数据上报等等)。这种情况传统的做法是每个地方都调用一遍相关接口 API。

再看上图,把验证这块整体框出来,可以形象地理解为就像一个板子,这块板子插入上面的逻辑流程。

再举个例子,iOS 里想在所有 Controller 的 ViewDidAppear 里加行日志,可以用 AOP 很好地实现。

3.1.2 Runtime Method Swizzling

介绍了 AOP 的基本概念,我们介绍下如何在 iOS 里实现 AOP 思想。这就引出了 Runtime(运行时)里的方法交换(Method Swizzling)。

我们常说 Objective-C 是一种动态语言,它总是把尽可能多的决定从编译和链接延迟到运行时执行。运行时是通过一套 C 语言 API 实现。runtime 相关的代码是开源的,感兴趣的同学可以看下相关的源码

有两种方式可以实现方法交换:

3.1.2.1 把两个 SEL 指向的 IMP 进行交换
struct objc_method {
    SEL _Nonnull method_name      
    char * _Nullable method_types 
    IMP _Nonnull method_imp       
}                                 

苹果有提供对应的 API 接口,如method_exchangeImplementations()

简单的使用方法交换会引起一些问题:

  • 不是线程安全的(Method swizzling is not atomic)
  • 潜在的命名冲突(Possible naming conflicts)
  • 改变方法的参数(Swizzling changes the method's arguments)
  • 继承问题(The order of swizzles matters)

有一些优秀的第三方开源框架在系统方法基础上提供了相对比较安全的方法交换。如RSSwizzle

3.1.2.2 消息转发拦截

我们知道,OC 发送消息时如果无法识别一个 Selector 时,会进行消息转发服务。消息转发分为三步, 1. 方法解析处理,2. 备援接受者,3. 完整的消息转发。

Aspects 是一套经典的应用 AOP 思想的 iOS 框架,它具有良好的用户体验,比较安全,支持撤销等优点。它的总体方案是参考 KVO,通过动态生成子类,子类把原方法的 IMP 动态指向 _objc_msgForward,当方法触发的时候,会直接进行消息转发。 通过把 forwardInvocation 指向自定义的方法,在自定义的方法里进行拦截操作处理。注意:Aspects 和 method_exchangeImplementations 同时使用会有冲突。

3.2 事件的唯一标识(即 ID) 如何确定。

要实现埋点事件的唯一性,需要对每个用户操作确定一个唯一标识,以此区分不同的事件。

下面介绍的方法和 XPath 的思路是相同的,XPath 是一门在 XML 文档中查找信息的语言,使用路径表达式来选取 XML 文档中的节点或节点集。

我们知道 APP 所有的页面可以看做一颗树的结构,对于屏幕中任何一个 view 对象,都可以得到一条唯一的从 window 到它的 path 路径。唯一标识可以由 path 路径、类名和一些属性的值来确定,称为 viewPath。示例如下:

上面这张图是一个button所在层级的描述,可以生成唯一的标识如下(使用SensorsData的结果):

UINavigationController/AutoTrackViewController/UIView/UIButton[(jjf_varE='47ee0929e87610f27936c63be82fc702a00431b4')]

这里生成 viewPath 会把 UIWindow 和系统的一些 Controller 忽略掉,减少 viewPath 的长度。还会做一些优化,如果路径中多个 view 的层级相同,会加上 view 在 superview 的 index 作为区分。

3.3 圈选如何实现。

圈选是可视化和无埋点的重要一环,主要采用客户端和 Web 端进行长连接,定期发送屏幕截图和控件树。Web 端根据屏幕截图和控件树进行展示还原。用户可在 Web 端进行圈选,并将圈选的配置下发给学生端。


图片来源于 SensorsData

3.3.1 屏幕序列化

序列化是将对象的状态信息转换为可以存储或传输的形式的过程。整个序列化过程的算法是,将 UI 对象加入到未访问队列中,从未访问队列中取一个对象访问,并序列化保存到已访问队列中。访问过程中如果对象存在子对象,则将子对象也加入到未访问队列中等待后续访问,如此递归到所有对象都已访问并序列化。

3.3.2 其他

数据传输一般是使用 WebSocket 长连接。
还有其他一些细节,如圈选配置文件解析等。

总结

没有一种埋点方案适用所有的场景,我们需要根据不同的场景挑选适合的埋点方案,代码埋点和无埋点是可以共存和相辅相成的。

End

本文参考了大量苹果官方文档和源码,以及第三方埋点框架。
下面列出部分第三方埋点框架:

  1. Mixpanel(开源)
  2. SensorsData(神策)(开源)
  3. Heap
  4. GrowingIO
  5. MTA(腾讯移动分析)
  6. 友盟
  7. TalkingData
  8. MTJ(百度移动统计)
  9. GoogleAnalytics(谷歌统计)
  10. HubbleData(网易内部使用)
  11. 此外,iOS无埋点数据SDK实践之路iOS无埋点数据SDK的整体设计与技术实现这两篇文章实现讲述了业务数据无埋点的方案。主要思路是提前配置eventID和业务参数的KVC,对业务代码有一定的要求,感兴趣的可以深入学习。

本文内容为原创, 转载请注明出处~
部分图片来源于网络,如有侵权,请联系我删除~

如有错误,欢迎指正~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 前言 最近跟同事花了点时间来思考可视化埋点,并没有什么突破性的进展,不过市面上很多关于可视化埋点的技术文章都在讲达...
    daixunry阅读 7,973评论 1 38
  • https://mp.weixin.qq.com/s/u-HmmrSAgtER1N2pKxCm0A 随着公司业务的...
    海浪萌物阅读 3,069评论 1 1
  • 前言 随着公司业务的发展,数据的重要性日益体现出来。 数据埋点的准确和全面性显得尤为重要。通过精准和详细的数据,后...
    MMR无与伦比阅读 5,895评论 2 13
  • 写在题前:文章为本人原创, 如果文章转载,必须标明作者与出处,并将原文链接以及github地址附在文章首行, 否则...
    SandyLoo阅读 21,109评论 22 150
  • 概念 埋点,是对网页、APP或后台等应用程序进行数据采集的一种行为。通过埋点,可以采集用户在应用中的行为,用于分析...
    凌空御风阅读 2,423评论 1 7