埋点数据作为推荐、搜索、产品优化的基石,其数据质量的重要性不言而喻,而要保障埋点数据的质量,埋点验证则首当其冲。工欲善其事必先利其器,要做好埋点验证会面临很多技术挑战:易用性、准确性、实时性、稳定性、扩展性,如何攻克这些挑战呢,其实还是技术,这也是本文的主旨所在。
目前埋点验证已在字节内部得到广泛使用,通过一键扫码开启验证、实时上报验证、自动生成验证报告,解决了埋点数据验证难、埋点质量保障难的问题。
本文将分为上下篇推送,上篇聚焦埋点验证流程和技术架构,下篇将分享技术挑战和解决方案。
文 | 志荣
来自字节跳动数据平台开发套件团队
技术挑战
-
易用性:快速接入埋点验证,快速开始埋点验证
-
准确性:埋点验证结果准确、用户可信
-
实时性:埋点数据实时可见
-
稳定性:埋点数据可靠不丢失
-
扩展性:快速接入新的埋点数据格式
易用性
快速接入 埋点 验证,快速开始埋点验证
SDK
-
快速接入埋点验证
-
SDK提供“埋点验证开关”,客户端集成SDK的时候,可根据不同环境来配置是否开启“埋点验证开关”
-
SDK层判断如果开启“埋点验证开关”,埋点数据会双发,此过程对业务是透明的
-
“线上埋点通道”数据量太大
-
SDK层线上上报逻辑是采用微批的形式,默认1分钟从客户端上报一次,而埋点验证要求实时性,所以采用单独的通道
-
双发的原因或者为什么不从“线上埋点通道”取数?这里主要考虑两个原因:
| 端 | SDK | 如何开启埋点验证开关 | | 客户端 | Android SDK IOS SDK | Android、IOS提供API,开关默认是关闭的,业务侧集成的时候可选择在“域内测试包”打开此开关 | | 服务端 | Go SDK Java SDK Python SDK | 服务端会自行判断是否是非线上环境,如果是非线上环境,会默认开启“埋点验证开关”
| | web端 | JS SDK 浏览器插件 | 1. JS SDK采用和客户端SDK一样的逻辑
- 为了使用方便,我们也提供了浏览器插件,用户只需打开此插件即可,无需关注“埋点验证开关” |
扫码连接
-
快速开始埋点验证
-
连接流程
-
建立WS连接:服务端和验证平台建立长连接,用于通信
-
ws_id:验证平台根据ws_id生成二维码
-
扫码:客户端扫描二维码
-
获取并打开验证开关:客户端获取设备信息并且打开埋点验证开关
-
上报device_id:客户端将长连接信息和设备信息上报至服务端
-
下发device_id:服务端将设备信息推送到验证平台
-
开始验证:埋点验证平台进入验证阶段
-
上报埋点:客户端开始上报埋点
-
推送埋点:服务端将埋点推送到验证平台
-
下发原理
-
客户端上报的埋点数据中含有设备信息
-
用户通过扫码在验证平台回填设备信息
-
服务端接收到埋点数据后,将埋点数据中的设备信息和验证平台的设备信息进行匹配,如果匹配则将埋点数据进行下发
准确性
埋点 验证结果准确、用户可信
埋点验证引擎必须保证埋点验证结果的准确性,才能降低验证成本。针对埋点数据本身的格式验证,我们采用了JsonSchema作为验证手段,以支持完善的验证规则、可信的验证结果。上文中的“规则生成器”、“规则选择器”、“埋点验证器”也都在一定程度上保证了埋点验证结果的准确性。
埋点方案
event:video_play
- 埋点名称:video_play
- 参数信息
- (名称、类型、是否必填、值校验、是否是场景条件)
- enter_from,string,必传,固定值(login),是
- duration,integer,必传,值无限制,否
- type,integer,必传,枚举(1,2,3),否
埋点规则
jsonSchema
{
"$schema":"https://json-schema.org/draft/2019-09/schema",
"type":"object",
"properties":{
"params":{
"type":"object",
"properties":{
"duration":{
"type":"integer"
},
"enter_from":{
"type":"string",
"enum":[
"login"
]
},
"type":{
"type":"integer",
"enum":[
1,
2,
3
]
}
},
"required":[
"duration",
"enter_from",
"type"
]
}
},
"required":[
"params"
]
}
埋点数据
event:video_play
{
"app_id":100,
"event":"click",
"params":{
"enter_from":"login",
"duration":1,
"type":3
}
}
验证结果
event:video_play
实时性
埋点数据实时可见
埋点验证场景下,服务端和验证平台需要频繁地进行数据交互,所以我们自建了Push服务(基于WebSocket的封装),能够保证数据的实时畅通性
Push服务目标
-
基于WebSocket实现一套通用长连接通讯协议,能实现同一个客户端上的不同业务共享同一个长连接通道,并实现可靠的心跳机制。
-
客户端和服务端基于通用长连接通讯协议实现一个稳定可靠的全双工通道。
-
客户端实现一个通用的SDK,服务端实现一个通用接入层。
-
客户端SDK,服务端接入层,都要很方便后续service接入。
-
Push服务定期做打点监控,同时开放http的Admin接口,方便系统的监控和查看服务状态
Push服务优势
-
连接稳定性:Push服务分为两个组件Push和Backone,实现了业务和推送解耦。push面向客户端连接,设计尽可能简单,需保持大量客户端活跃连接,避免了业务服务更新时不影响客户端连接
-
服务隔离性:不同的业务服务接入push服务,会根据接入信息做集群隔离,避免业务之间互相影响
-
横向扩展性:当业务服务不断增多时,只需对push服务做横向扩容即可支持
Push服务流程
稳定性
埋点 数据可靠不丢失
SLA
-
定义:服务级别协议 (service-level agreement,即 SLA) 是服务提供方与客户之间的正式承诺,用来量化服务水平(质量、可用性、责任)
-
埋点验证服务:服务的特征是实时,所以衡量埋点验证不可用的手段是“数据延迟”,即埋点从“上报”->“验证平台”的 p99 超过 3s 即视为不可用,日常 p99 在 1s
| 可用性 | 双月故障时间 | 年故障时间 | | 99.9% | 86.4m | 8.64 h |
措施
-
为了保证“SLA”,我们做了一系列的保护措施
-
日志转换器:客户端、服务端、web 端上报的是原始日志格式,需要转换为埋点验证日志格式后进行验证
| 措施 | 说明 | | 监控 | 为了保证线上服务的稳定性,对线上流量进行监控,支持按app粒度进行查看app粒度的QPS,以便发生报警的时候,可以快速定位到具体是哪个app的流量异常 | | 报警 | 对线上流量进行报警,报警策略的设置如下:* 当前QPS达到最大qps的50%的时候,报警级别为warning,提示需要注意
- 当前QPS达到最大qps的70%的时候,报警级别为critical,提示必须处理 | | 限流 | 当发生报警的时候,通过监控定位出具体app,做如下处理:1. 针对此app数据进行限流,确保其他app不会受到影响
-
联系app业务方,确认此app流量是否为异常流量
-
如果是异常流量,对异常流量进行处理,处理后撤销限流
-
如果是正常流量,那么埋点验证服务进行处理 | | 降级 | 实时验证流程是当前的主要业务,当发现流量突增,限流无法解决的情况下,对自动化验证流程进行降级,确保主要业务的稳定性 |
扩展性
快速接入新的埋点数据格式
- 提供可插拔的“日志转换器插件”,服务高内聚,可支持各种日志格式快速接入、验证
展望
埋点验证是保障埋点质量的有效方式,此方式属于事前验证,适用于埋点频繁变化的业务场景,需要一定程度的人工介入,能够解决基本的埋点质量问题。 但是对于核心埋点场景来说,这种方式的验证成本较高,需要重复的人力投入,为了解决核心埋点验证成本高的问题,我们正在探索落地其他方式:
- 回归验证(自动化验证): 伴随每次发版,核心埋点都需要进行回归验证,目前我们通过内部其他团队的合作实现了自动化验证功能来支撑回归验证,当前已有一部分业务正在使用,极大地降低了验证核心埋点的成本
- 事后验证: 经过事前验证、回归验证,埋点质量基本能得到很好的保障。但为了更好的保障我们也在探索事后验证的场景和落地:
- 质量大盘:通过“规则引擎”,结合“质量模型”对埋点数据进行质量评估,得出各个维度的“质量评分”,然后针对质量问题进行专项修复,进一步提高埋点质量。
- 质量工具:提供监控计划,业务可以针对自己关注的埋点配置监控报警,当线上出现质量问题,会发送质量报告给业务,及时止损。
- 全链路埋点质量保障: 事前验证、回归验证、事后验证贯穿埋点的生命周期,打通这三个流程,从而形成埋点质量保障全链路,彻底解决埋点质量问题。
产品介绍
火山引擎大数据研发治理套件DataLeap
一站式数据中台套件,帮助用户快速完成数据集成、开发、运维、治理、资产、安全等全套数据中台建设,帮助数据团队有效的降低工作成本和数据维护成本、挖掘数据价值、为企业决策提供数据支撑。 后台回复数字“2”了解产品。
字节跳动数据平台开发套件团队火热招人中!
后台回复“招聘”,获取岗位信息。
点击 阅读原文
进入官网
, 了解DataLeap更多产品信息