7

大厂经验:埋点数据质量之埋点验证

 3 years ago
source link: https://xie.infoq.cn/article/fa3f8e201e8eb032457db1f39
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.

背景介绍

当我们根据埋点sdk接入文档完成了埋点的代码开发之后,都会面临数据质量相关问题,一般会从以下两个方面来进行验证:

  1. 埋点日志是否能上报成功

  2. 验证埋点数据是否正确

如果在没有埋点验证工具的情况下,我们先来看看是如何解决这件事。如果你是PC端的话,可以打开chrome开发者工具去查看它网络请求,看看http状态码是不是200,携带字段是否正确。

2MzqmyU.jpg!mobile

如果你是客户端那就比较麻烦一些,需要装一个抓包工具(比如Charles)去抓包客户端的请求,然后再去检查你的埋点日志上报是否正确。

IrAjimi.jpg!mobile

3mquMrN.jpg!mobile

在没有埋点验证工具的情况下,我们进行埋点验证还是比较繁琐的,上手门槛比较高,而且直观性也比较差。所以我们需要好用的埋点验证工具来提高我们的工作效率,那么接下来我们就讨论一下如何设计一个埋点验证工具。

客户端验证vs服务端验证

首先先解释一下这两个名词的意思:

  • 客户端验证。 监听客户端的埋点上报,并提供一个可视化的工具展示所有埋点的上报结果用于埋点验证。

  • 服务端验证。 将所有客户端的埋点日志全部收集上来,由服务端做后续的埋点验证工作。

选择不同的埋点验证,后续实现方式也会不一样,所以我们先比较这两种方式的优缺点:

比较项客户端验证服务端验证比较结果 上手门槛需要在客户端安装埋点验证工具有统一的埋点验证网页,不需要用户安装服务端验证胜利后续升级维护只能通知用户手动升级,不能统一升级可统一升级服务端验证胜利日志区分不需要对日志进行区分需要对上报上来的日志进行区分客户端胜利能否离线工作可离线工作不可离线工作客户端胜利功能拓展性可依赖端的能力做定制化需求无法依赖端的能力客户端胜利

通过对比发现,客户端验证可以依赖客户端的能力,它在功能拓展性上是要优于服务端验证的,而服务端验证由于是把日志统一收上来的,所以它在上手门槛和维护性上要强于客户端验证的。从埋点验证工具使用场景上来说不太需要依赖客户端的能力,相比较上手门槛和后续升级维护更加重要一些,所以推荐使用服务端验证。

埋点染色

上面我们比较了客户端验证和服务端验证的区别,如果想做服务端验证的话,首先我们需要解决的就是如何拿到你想要验证的日志。这里就要引出一个新的概念“埋点染色”,其含义就是在客户端上报日志时给需要验证的日志打上独特的标识。接下来我们讲一下不同客户端是如何进行埋点染色。

Web

web的埋点染色相对来说简单很多,我们可以借助url去进行埋点的染色。比如:

https://www.taobao.com?debugId=cafebabe

然后我们通过如下代码去获取到这个debugId,然后在上报的日志加一个debugId的字段。

functiongetArgsQuery(){
varsearchStr =window.location.search.length >0?window.location.search.substring(1) :'';
varsearchStrArray = searchStr.length >0? searchStr.split('&') : [];
varargs = {};
searchStrArray.forEach((item) =>{
varname =decodeURIComponent(item.split('=')[0]);
varvalue =decodeURIComponent(item.split('=')[1]);
args[name] = value;
});
returnargs;
}

getArgsQuery().debugId//cafebabe
//拿到debugId之后就可以跳用sdk的api去种下debugId
Tracker.verificate(debugId);

App

scheme

首先设计一个schemeUrl比如:

tracker://tracking/verification?debugId=cafebabe

接下来我们就是在App端去实现对这个schemeUrl的拦截,这里以安卓代码为例:

AndroidManifest.xml

<activityandroid:name=".TrackingVerificationActivity">
<intent-filter>
<actionandroid:name="android.intent.action.VIEW"/>
<categoryandroid:name="android.intent.category.DEFAULT"/>
<categoryandroid:name="android.intent.category.BROWSABLE"/>
<!--配置scheme-->
<data
android:scheme="tracker"/>
</intent-filter>
</activity>

获取debugId并种下:

Intent intent = getIntent();
Uri uri = intent.getData();
if(uri !=null) {
String debugId = uri.getQueryParameter("debugId");
//调用SDK种下debugId
Tracker.verificate(debugId);
}

最后我们实现一个H5中间页就可以完成完整的流程:

<!DOCTYPEhtml>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>App-scheme验证</title>
</head>
<body>
<ahref="tracker://tracking/verification?debugId=cafebabe">开始验证</a>
</body>
</html>

完整流程如下:

emMrmeZ.jpg!mobile

jsBridge

首页在App端实现jsBridge的代码示例:

publicclassActivityextendsAppCompatActivity{
privateWebView webView;

publicclassInjectNativeObject{// 注入到JavaScript的对象
privateContext context;
publicInjectNativeObject(Context context){
this.context = context;
}
@JavascriptInterface
publicvoidverificate(String debugId){// 接受前端传来的参数
//实现种debugId的逻辑
}

}

@SuppressLint("SetJavaScriptEnabled")
@Override
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.trackWebView);
webView.getSettings().setJavaScriptEnabled(true);
// JS注入
webView.addJavascriptInterface(newInjectNativeObject(this),"Tracker");
}

}

其次设计H5中间页,在该页面中调用。

<!DOCTYPEhtml>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>App-jsBridge验证</title>
</head>
<body>
<aonclick="startVerification()">开始验证</a>
</body>
<script>
functionstartVerification(){
vardebugId =getArgsQuery().debugId;
if(debugId){
Tracker.verificate({
debugId
},function(res){
alert('开始验证');
})
}
}
</script>
</html>

完整流程如下:

2I3A3i3.jpg!mobile

1.打开IDE,添加编译模式。

YnE7fev.jpg!mobile

2.配置启动参数,把debugId配置进去。

feMJbaj.jpg!mobile

3.在App.onLaunch生命周期中获取到debugId,并设置debugId。

App({
aplus: aplus,
onLaunch:function(options){
//获取debugId
const{ query } = options;
const{ debugId } = query;
//调用SDK设置debugId
Tracker.verificate(debugId);
}
})

埋点日志收集流程

当客户端对需要验证的埋点日志都带独特的标识之后,我们就可以根据这个独特的标识去我们的埋点日志仓库去捞取我们所需要验证的日志。大致流程如下:

AV73YvI.jpg!mobile

这里我们需要注意一个点就是埋点日志落库其实一个比较慢的过程,因此我们如果要等到埋点日志落到数据仓库再去获取我们需要日志的话,就会有一个等待时间,这个埋点时效性就没有办法保证。鉴于这个原因我们的流程需要改进一下。

NnUJzaJ.jpg!mobile

除了正常的埋点日志落库流程,我们额外新增一个带有debugId的日志落库到redis,由于redis强大的性能,可以保障我们埋点验证的时效性。

小结

本章节我们在开头详细阐述了为啥要做埋点验证,目前市场上埋点验证的方式有两种,一种是客户端验证,一种是服务端验证,为了让大家更好了解这两种方式,我们详细比较了二者的区别。通过比较分析我们最后选择服务端验证这种方式。服务端验证首先要解决的事情就是如何获取到你想要验证的埋点日志,通过这个问题我们引出了“埋点染色“的概念,然后铺开了讲一下不同类型客户端是如何进行埋点染色的。最后我们再综合起来讲一下埋点日志收集流程大致是什么样子的。在本章节我们已经解决了如何获取需要验证的埋点日志的问题,后面的文章我们会讲一下如何去验证埋点日志,敬请期待。

————— 招聘广告分界线 —————

某大厂大数据团队招聘前端、Java、C++、数据开发、Android、iOS、安全技术专家,级别不限,欢迎大家私信联系。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK