27

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

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzI1NDc5MzIxMw%3D%3D&%3Bmid=2247487737&%3Bidx=1&%3Bsn=8824d76646103da295ff5072ec5b4f4d
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

开源项目专题系列

(八)

1.开源项目名称 magpie_log

2.github地址:

https://github.com/wuba/magpie_log

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

l i v e

5 8

F l u t t e r 5 8

7 : 0 0

3UbaQzN.jpg!web

全文大纲如下:

  • 项目背景

  • 项目架构

  • 具体实现细节

  • 流程与展示

  • 展望

  • 总结

  • 作者介绍

项目背景

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

2miqaqR.png!web

图1 现有的埋点方案对比

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

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

U7fMbqU.png!web

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

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

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

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

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

项目架构

IbAnQrn.png!web

图3 项目架构

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

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

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

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

具体实现细节解析

FVriQnN.png!web

图4 细节解析

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

 1、圈选拦截

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

z2mqYnQ.png!web

图5 圈选拦截

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

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

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

NvYRVfz.png!web

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

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

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

 2、参数级联勾选

6r6RJrr.png!web

图7 参数级联勾选

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

 3、列表形式拦截

q6zQRbR.png!web

图8 列表形式

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

 4、setState()拦截

AzaENve.png!web

图9 setState拦截

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

 5、页面跳转拦截

2iQNBz2.png!web

图10 页面跳转拦截

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

 6、手动埋点

aueUNnn.png!web

图11 配置

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


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

 7、圈选配置

vuIRJzr.png!web

图12 配置

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

 8、埋点上报

UzEJnyQ.png!web

图13 埋点上报

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

流程与展示

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

ZJVbIjv.png!web

图14 基本流程

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

bMra2ya.png!web

图15 详细工作流程

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

jERZfuj.png!web

图16 展示

展望

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

MfuIvy6.png!web

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

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

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

总结

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

项目已开源!开源地址:

https://github.com/wuba/magpie_log

作者介绍

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

阅读推荐

开源|Magpie:组件库详解

详解站点压测利器——nGrinder

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

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

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

Nb2iMvQ.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK