查看原文
其他

开源|Magpie可视化圈选埋点实践

林乐洋 58技术 2022-03-15





开源项目专题系列(八)
1.开源项目名称magpie_log2.github地址:

https://github.com/wuba/magpie_log

3.简介:magpie_log是基于flutter的一个跨平台可视化圈选埋点的解决方案。旨在解决手动埋点耦合业务,现有Native自动埋点方案无法带参,以及混合开发中因埋点导致交互频繁影响性能等问题,成为flutter埋点的一站式解决方案




live58技术沙龙活动第五期Flutter在58的应用实践系列话题本周日晚7:00准时开幕点击图片即可报名抢座


全文大纲如下:

  • 项目背景
  • 项目架构
  • 具体实现细节
  • 流程与展示
  • 展望
  • 总结
  • 作者介绍


项目背景

native埋点的主要痛点是和业务逻辑的强耦合,导致开发效率低以及无法动态的配置修改。针对这些痛点,有很多native侧成熟的自动埋点方案。但是目前flutter的自动埋点方案还是空白的,我们想在flutter上实现解耦,动态的添加埋点,肯定是要借鉴native现有的埋点方案,具体要采用哪种方式,首先要做简单的对比。




图1 现有的埋点方案对比

现有的自动埋点方案,主要可以分为两类:一种是基于动态代理的可视化埋点,一种是基于ASM的全埋点方案。两者的主要区别就是全埋点支持回溯,可视化不支持。相对的,可视化埋点可以可视化配置需要上传的数据,全埋点方案比较耗流量和性能。经过调研,全埋点上传的数据大部分是不会使用的,但我们又需要可视化的页面来方便操作,因此基于可视化埋点的思路,并结合flutter的特色进行了优化改造。

确定选型之后就是一些具体的方案和思考:





图2 问题点思考
  1. 如何拦截尽可能多的事件,native拦截onClick能不能在flutter用,如何用?

  2. native的圈选痛点无法带与ui无关的参数,flutter是基于MVVM的架构是否可以通过ViewModel实现圈选带参?

  3. 可视化如何做,在服务端还是客户端做?

  4. 如果是Hybrid形式接入flutter,如何做到和原有埋点系统无缝衔接,并且减少通讯频次?

带着这些问题和思考,不断的调研,实践,最终设计了magpie_log的整体架构。


项目架构





图3 项目架构

  • 首先解决如何拦截尽可能多的事件,选择实现基于redux的action拦截、基于Navigator的跳转拦截和setState()拦截,同时为了覆盖全埋点,magpie_log还提供手动埋点,后面会详细说明为什么怎么做;

  • 如何解决圈选带参,由于是MVVM的模式,view绑定着页面级别的ViewModel(如Redux有全局的store数据),也就是说可以通过View拿到对应的ViewModel数据,进而实现带参;

  • 如何实现可视化,由于开发成本的原因,magpie_log最终选择在native页面实现圈选操作,native界面相对较小,但是通过UE同学的设计尽可能要方便用户操作,并且功能全面,加入了配置,管理等功能;

  • 为了解决通讯频繁的问题我们了设计定时器,计数器减少交互,为了解决无缝衔接,快速接入的问题,magpie_log分别实现native,flutter的上报封装使得接入十分方便。


具体实现细节解析





图4 细节解析

下面主要介绍各种功能的具体实现细节:

 1、圈选拦截

首先也是最关键的一个问题,就是如何拦截尽可能多的事件。基本上开始的第一周都是在圈选拦截的技术选型。什么样的技术选型最适合呢?





图5 圈选拦截

首先想到的肯定是native的思路,通过AOP的思想,拦截OnClick事件,但是很快发现拦截所有的事件就很困难,而且即使拦截Detector,也获取不到树形结构,因为flutter的widget本身是拿不到层级结构的,element可以,但是我们能拦截到的是widget,通过widget获取不到element。也就是说view的唯一标识无法确认。总结一下就是思路不清晰,实现困难,逆天而行。

最后我们几经波折想到了大部分flutter的应用都会引用状态管理,其中最常用的是redux,并且通过redux可以拦截所有的action事件,并在中间件或者reducer里面处理逻辑;符合mvvm的设计模式;唯一标识可以通过actionName和页面路由做唯一的标识。这种实现方式思路清晰,实现也相对简单,成本最低。这样项目才算开始走上正轨。

由于的主要圈选事件的触发是基于redux,先介绍一下redux:





图6 redux
  • 很多做flutter开发的同学都遇到过这个问题,就是如图9所示,当子控件触发事件通知其他组件更新,会调用跟控件的setState,所有的子View都会刷新,无法实现局部刷新。

  • 当项目十分庞大,页面更新会很混乱,耦合严重,因此官方有提出了flutter-redux状态管理插件,底层是Inheritedwighet,很好的解决了这些问题,想要了解的可以看官方的文档,这里不赘述。

当然redux也有很多的问题,我在后面会讲到一些优化的方案。


 2、参数级联勾选





图7 参数级联勾选

native的自动埋点方案的一个很大的问题就是可带参数有限,而且可选的参数必须是和UI密切相关的;然而如果基于redux状态管理,获取参数就有了契机,有全局的store数据,在拦截事件的同时能过获取store数据,并且通过store的层级数据做递归处理,使得数据层次化,进而在页面展示,可供用户进行圈选。


 3、列表形式拦截





图8 列表形式

列表形式的数据也是自动埋点的一个难点,包括遍历以及上报数据的过程,现阶段的处理方式是在配置阶段对list的数据进行特殊处理。取list的第一条数据做配置规范,触发点击等事件的时候需要传递index参数,表明点击的位置,这样方便统计。


 4、setState()拦截





图9 setState拦截

如果你真的真的没有选择redux做状态管理,magpie_log也提供了setState的拦截方式———WidgetLogState。需要继承,并且实现对应的方法,可以说耦合比较重,并不建议过多的使用。


 5、页面跳转拦截





图10 页面跳转拦截

除了点击展示等事件,页面的曝光统计也是非常常见的埋点场景,因此magpie_log也支持页面的统计。实现方式主要就是基于Navigator,需要设置LogObserver监听。当监听到页面push操作时,debug模式拦截唤起圈选页面,Magpie_log通过pop和push并维护了一个自己的页面堆栈,页面堆栈主要是用于获取当前路由标识,标识埋点的唯一性。


 6、手动埋点





图11 配置
MagpieStatisticsHandler.instance.writeData({'data': '手动埋点数据示例'});

所有的自动埋点都不能保证覆盖所有的埋点,因此我们也提供了手动埋点的api,方便统一上传管理。


 7、圈选配置





图12 配置

圈选配置的主要分4个部分,埋点配置,配置文件,基础配置和上报配置。
埋点配置是有一个个埋点的配置项组成,包括标识,路由,类型组成的唯一标识,以及参数和备注。
配置文件的管理是分页面ui配置Api,内存缓存,磁盘和assets5个部分,初始化配置是从assest取出配置文件到磁盘,同步内存,所有页面操作者api接口大都是和内存打交道,只有最后生成文件保存的时候做持久化存储,避免过多的交互。
基础配置指的是一些ui上面可控制的配置。


 8、埋点上报





图13 埋点上报

埋点上报单独拿出来,为了说明除了flutter侧的回调,避免native和flutter过多的交互影响性能,magpie_log提供逐条上报,定时上报,计数上报的选项,同时为了解决大多项目都是混合开发的模式,解决已有native系统的问题,并且提供了Android和ios的channelApi,方便或者项目的引用。


流程与展示

简单来说,流程只需要4部分,既触发、圈选、配置和运行时上报:





图14 基本流程

详细工作流程可以参考下面的图15:





图15 详细工作流程

随着App打开,进行配置文件的初始化,主要工作是把assets里面的文件转移到磁盘。当用户触发Action事件,会根据用户当前是debug还是release,如果是debug会走圈选配置的流程,最后生成埋点的配置文件;如果是release模式会走线上埋点的上报流程,当然前提是你有相关的对应配置。
下面是对应流程的展示:





图16 展示


展望

跨平台的更加全面的动态化可视化的圈选埋点解决方案:





图17 规划展望
  1. 动态化:服务端配合,动态化配置的上传和下发;

  2. 全面:redux一个App一个store对业务并行开发并不友好,改造redux;

  3. 级联赋值问题 导致日志参数和数据一样,可以增加用户配置.


总结

无论你的项目是纯flutter,还是混合开发的项目,magpie_log都会给你提供一个很好用的埋点解决方案,当然有一些问题和局限,期待和大家一起沟通改进。

项目已开源!开源地址:

https://github.com/wuba/magpie_log


作者介绍
林乐洋,58同城Android高级开发工程师,58同城APP黄页业务线负责人,58商家通Android负责人。



END

阅读推荐

开源|Magpie:组件库详解

详解站点压测利器——nGrinder

开源|Magpie:Magpie在安居客有料业务的落地实践

开源|Magpie:混合开发工程化框架

Go服务在容器内CPU使用率异常问题排查手记



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存