3、数据采集层监控:SDK埋点校验、日志采集成功率、采集端延迟监控、采集端错误率统计
数据采集层,是整个埋点体系的「第一公里」。
这一层要是出了问题,后面所有的分析、报表、模型,全都是在垃圾数据上跳舞。我见过太多团队,花大价钱搭了实时数仓、买了BI工具,结果发现埋点数据从源头就丢了30%——那感觉,就像你修了一条高速公路,结果收费站全塌了。
所以,这一章我们重点盯住四个核心指标:SDK埋点校验、日志采集成功率、采集端延迟、采集端错误率。说白了,就是确保数据「发得出、收得到、来得快、不出错」。
3.1 SDK埋点校验:从源头掐断脏数据
SDK埋上去之后,第一件事不是看数据量,而是看「埋对了没有」。我曾经在一个电商项目中,发现「加入购物车」事件上报了100万次,但「提交订单」只有2000次——转化率低得离谱。查了半天,原来是SDK版本升级时,某个参数名从 product_id 改成了 item_id,服务端没同步更新,导致订单事件全部解析失败。
从那以后,我养成了一个习惯:埋点校验必须自动化,而且要在数据进入管道之前完成。
校验的核心维度:
- 事件名合法性:是否在预定义的事件字典中?有没有拼写错误?
- 参数完整性:必填字段是否缺失?比如「支付事件」必须带上
order_id和amount。 - 参数类型与格式:
price应该是数字,不能传字符串;timestamp应该是毫秒级时间戳,不能传 "2024-01-01"。 - 值域范围:
age不能是负数,rating应该在1-5之间。
具体怎么做?我建议在SDK内部集成一个轻量级校验模块,在数据发送前做一次快速检查。校验不通过的事件,直接丢弃并上报错误日志,而不是让它污染整个管道。
// 伪代码示例:SDK端校验逻辑
function validateEvent(event) {
const errors = [];
if (!eventDict.includes(event.name)) {
errors.push(`未知事件名: ${event.name}`);
}
if (event.requiredFields) {
event.requiredFields.forEach(field => {
if (event.params[field] === undefined) {
errors.push(`缺少必填字段: ${field}`);
}
});
}
if (event.params.price && typeof event.params.price !== 'number') {
errors.push(`price 字段类型错误,期望 number,实际 ${typeof event.params.price}`);
}
return errors.length > 0 ? errors : null;
}
小技巧:校验规则可以做成可配置的JSON下发,这样不用发版就能调整校验逻辑。我一般把规则放在CDN上,SDK启动时拉取一次,既灵活又轻量。
3.2 日志采集成功率:别让数据「死」在半路
SDK发出数据后,能不能顺利到达服务端?这就是日志采集成功率要回答的问题。
计算公式很简单:
采集成功率 = 服务端成功接收的日志数 / SDK发送的日志数 × 100%
但难点在于——你怎么知道SDK「发送了多少」?
我常用的方案是双端计数+对账:
- SDK端:每发送一条日志,本地记录一个递增的序列号(seq_id),并定期上报「已发送计数」。
- 服务端:每收到一条日志,记录其seq_id,并统计「已接收计数」。
- 对账任务:每小时跑一次,比对两端计数。差值超过阈值(比如1%)就触发告警。
| 指标 | 正常范围 | 告警阈值 | 处理动作 |
|---|---|---|---|
| 采集成功率 | ≥ 99.5% | < 99% | 检查网络、SDK版本、服务端负载 |
| 单设备丢失率 | ≤ 0.5% | > 2% | 排查该设备SDK是否异常 |
| 对账延迟 | ≤ 5分钟 | > 30分钟 | 检查对账任务是否卡死 |
注意:不要只盯着整体成功率。我曾经遇到过一个案例,整体成功率99.8%,但某个渠道的Android低端机型成功率只有70%——因为那些手机内存不足,SDK在后台被系统杀掉了。所以,一定要按版本、渠道、机型、网络类型等维度拆开看。
3.3 采集端延迟监控:数据「快」才有价值
数据采集不仅要「全」,还要「快」。尤其是实时场景——用户刚点了个按钮,你5分钟后才收到事件,那还做什么实时推荐?
采集端延迟,我一般拆成三段来监控:
- SDK发送延迟:事件产生到SDK发出请求的时间。通常受SDK内部队列、网络状态影响。
- 网络传输延迟:请求发出到服务端接收的时间。主要看网络质量。
- 服务端处理延迟:服务端接收到写入消息队列的时间。受服务端负载影响。
怎么监控?在SDK端打时间戳,服务端收到后算差值。我习惯在每条日志里加三个字段:
{
"event_time": 1700000000000, // 事件发生时间(客户端)
"send_time": 1700000001000, // SDK发送时间
"server_receive_time": 1700000001500 // 服务端接收时间(由服务端填充)
}
这样,我们就可以算出:
send_time - event_time= SDK内部排队延迟server_receive_time - send_time= 网络+服务端处理延迟
我的经验阈值:
- SDK内部延迟:应 < 500ms,超过1秒说明SDK队列积压严重。
- 网络+服务端延迟:应 < 2秒,超过5秒就要排查网络或服务端瓶颈。
- P99延迟:整体应 < 3秒,否则实时场景基本不可用。
3.4 采集端错误率统计:别让异常「静默」
错误率,是数据质量的「晴雨表」。但很多团队只盯着「服务端5xx错误」,忽略了客户端侧的异常。
我建议把错误分成两类来监控:
- 客户端错误:SDK内部异常(如JSON序列化失败、本地存储写入失败)、网络错误(如DNS解析失败、连接超时)。
- 服务端错误:HTTP 4xx(参数校验失败)、5xx(服务端内部异常)、限流拒绝。
客户端错误怎么收集?SDK内部维护一个错误缓冲区,把错误信息暂存起来,每隔一段时间(比如5分钟)批量上报一次。注意,错误上报本身不能影响正常数据采集——我一般用独立的、更轻量的通道来传错误日志。
// 错误上报示例
function reportError(error) {
const errorLog = {
type: error.type, // 'network' | 'parse' | 'storage'
message: error.message,
stack: error.stack,
timestamp: Date.now(),
device_id: getDeviceId()
};
// 使用独立的、低优先级的请求发送
sendBeacon('/error-collect', JSON.stringify(errorLog));
}
避坑指南:我曾经遇到过一个问题——错误率突然飙升到30%,但数据量没降。查了半天,发现是SDK里一个日志打印的bug,每次正常发送都会触发一个无害的warning,被错误收集模块当成异常上报了。所以,一定要给错误类型做白名单过滤,把已知的、无害的异常排除掉。
3.5 知识体系总览
下面这张图,把数据采集层监控的四个维度串起来了。你可以把它贴在墙上,每次排查问题时对照着看。