3、数据资产访问日志采集:日志埋点方案、日志格式规范、日志传输与存储

日志采集是整个热度分析的根基。说白了,你后面所有的报表、排行榜、冷热数据分层,都依赖这一层的数据质量。我见过太多项目,前期埋点随便搞搞,结果分析阶段发现字段对不上、时间戳乱跳、关键行为没记到……嗯,那时候再回头补日志,成本就高了。

这一章,我们聚焦三个核心问题:在哪埋、记什么、怎么传。

3.1 日志埋点方案:选对位置,事半功倍

埋点不是越多越好。你想想看,每个请求都打全量日志,存储和网络开销会迅速膨胀。我的原则是:只埋能回答业务问题的点。

对于数据资产热度分析,我们需要回答三个问题:

  • 谁(用户/应用)访问了什么(资产)?
  • 什么时候访问的?
  • 怎么访问的(读/写/预览/下载)?

基于这个思路,我通常推荐三种埋点方式组合使用:

埋点方式 适用场景 优点 缺点
网关层埋点 API 请求、数据服务调用 统一入口,覆盖全;改一次生效 无法捕获客户端缓存命中
应用层埋点 数据门户、BI 工具、Notebook 能记录业务语义(如“预览报表”) 需要业务方配合改造
存储层埋点 HDFS、Hive、Iceberg 等直接访问 最准确,无遗漏 解析审计日志成本高
我的经验: 优先做网关层埋点。我在上一家公司就是这么干的——所有数据请求统一经过一个 API 网关,在网关里加一个 Filter,一行代码就把请求路径、用户、时间、返回状态全记下来了。覆盖了 80% 的场景,剩下的 20% 靠应用层补。

3.2 日志格式规范:统一结构,避免混乱

格式不统一,解析起来就是灾难。我记得有一次排查问题,发现同一个字段在 A 系统叫 user_id,在 B 系统叫 uid,在 C 系统叫 userId……光做字段映射就花了两天。

所以我建议,从一开始就定一个统一的日志规范。下面是我常用的格式模板:

{
  "event_id": "uuid",                // 事件唯一 ID
  "timestamp": 1712563200000,        // 事件发生时间(毫秒时间戳)
  "user_id": "zhangsan",             // 用户标识
  "user_ip": "10.0.1.100",          // 客户端 IP
  "asset_type": "table",             // 资产类型:table / file / dashboard / report
  "asset_id": "hive.default.sales",  // 资产唯一标识
  "action": "query",                 // 操作类型:query / download / preview / share
  "duration_ms": 1234,               // 请求耗时(毫秒)
  "status": "success",               // 状态:success / fail
  "extra": {}                        // 扩展字段,按需填充
}

这里有几个关键点要注意:

  • 时间戳统一用毫秒,不要用字符串格式(比如 "2025-04-08 10:00:00"),否则排序和聚合都很麻烦。
  • 资产 ID 要全局唯一。我建议用 类型.层级.名称 的命名方式,比如 table.default.sales 或 file.hdfs.data_lake.raw.log。
  • 扩展字段保留。业务方可能临时需要加一些自定义属性,留一个 JSON 对象兜底,避免频繁改 schema。
避坑指南: 我曾经遇到过一个团队,日志里把用户 ID 和资产 ID 都放在 extra 字段里,导致后面做热度聚合时,不得不写一堆复杂的 JSON 解析逻辑。核心字段一定要放在顶层,别偷懒。

3.3 日志传输与存储:可靠、低延迟、可回溯

日志从产生到落地,中间要经过采集、缓冲、传输、存储四个环节。每个环节都可能丢数据,所以可靠性是第一位的。

我常用的架构是这样的:

日志采集与传输架构 应用服务 数据网关 存储引擎 日志采集 Agent(Filebeat / Fluentd) 消息队列(Kafka / Pulsar) 对象存储 / HDFS / ClickHouse 日志产生端 采集端 缓冲层 存储层

每个环节的选型要点:

3.3.1 采集端:轻量、无侵入

我推荐使用 Filebeat 或 Fluentd。它们的特点是:

  • 资源占用低,不会影响业务进程。
  • 支持多种输入源(文件、TCP、Kafka)。
  • 自带背压机制,当下游写入慢时,能自动降速。
关键配置: 记得开启 close_inactive 和 clean_removed,避免采集器长期持有已删除文件的句柄,导致内存泄漏。我踩过这个坑,线上 Filebeat 跑了两个月,内存涨到 2GB,就是因为没配这两个参数。

3.3.2 缓冲层:削峰填谷

日志流量有高峰(比如早上 9 点上班高峰),也有低谷。直接写存储,存储扛不住。所以中间加一层消息队列,比如 Kafka 或 Pulsar。

我个人的习惯是:

  • Topic 按资产类型拆分,比如 log-table、log-file、log-dashboard,方便下游独立消费。
  • 分区数至少 3 个,保证并行度。
  • 日志保留 7 天,方便回溯。

3.3.3 存储层:冷热分离

日志数据量很大,全量存热存储成本太高。我建议做分层:

存储层级 存储介质 保留周期 用途
热存储 ClickHouse / Elasticsearch 最近 30 天 实时查询、监控告警
温存储 HDFS / 对象存储(OSS/S3) 30 天 ~ 1 年 月度报表、趋势分析
冷存储 归档存储(Glacier / 冷存 OSS) 1 年以上 合规审计、历史回溯
注意: 日志写入存储时,一定要按日期分区。比如 ClickHouse 按 toYYYYMMDD(timestamp) 分区,HDFS 按 /logs/dt=2025-04-08/ 目录组织。否则后面做数据清理时,你会发现删数据比写数据还痛苦。

3.4 小结:日志采集的黄金法则

最后,我总结几条经验法则,供你参考:

  1. 埋点先想后做:先明确要分析什么热度指标,再决定埋哪些点。别为了埋点而埋点。
  2. 格式统一是底线:字段名、类型、时间格式,必须全团队拉齐。我建议把规范写进 Wiki,并在 CI 里加 schema 校验。
  3. 传输链路要可观测:在采集端、缓冲层、存储端都加监控,一旦日志延迟超过 5 分钟,立刻告警。日志丢了,热度分析就是无源之水。
  4. 存储成本要算清楚:日志量级通常是 TB/天级别,提前规划好冷热分层和压缩策略(比如用 Snappy 或 Zstd 压缩),能省下不少钱。