结论先行:把各部门的日志汇到一个平台,只是把数据放在了一起。要让一笔操作在几个系统的日志里串成一条,靠的是业务标识从入口一路传到末梢。四件事要在接入之前定下来:用什么当标识、每一层怎么把它写进日志、格式怎么统一、以及标识断掉之后怎么补。四件里少一件,平台上的数据就还是一堆各自为政的记录。
串不起来的三种情形
汇总完成之后做一次实测,多数环境会遇到下面三种情况。
- 入口生成的标识没往下传。前端或接入层生成了一个请求号,但调用后端时没带过去。后端各服务的日志因此各写各的,同一个标识只能在一段里找到。
- 中间件把上下文丢了。同步调用能传,进消息队列就断。生产者把消息投出去,消费者另起一个线程处理,原来那个标识不在线程上下文里,日志里就是空的。
- 有的系统根本没有入口标识。定时任务、批量作业、后台脚本没有用户请求,自然也没有请求号。这类日志往往只能按时间堆在一起,一笔作业涉及哪些系统说不清。
三种情形的共同点是:日志平台那边看不出异常。数据都在,只是对不上。
四件事,前两件是工程改造
四件事的性质不一样,工作量也不同。定标识和统一格式是定规矩,透传和补链要改代码。
| 环节 | 要定的事 | 落在谁手里 |
|---|---|---|
| 定标识 | 用什么字段当串联键,长度与字符集,是否允许重复 | 架构组定,各系统遵守 |
| 透传 | 调用、消息、线程池、异步任务四个位置各怎么带过去 | 各系统开发改 |
| 落盘 | 写入日志时的字段名、位置、时间格式与时区 | 日志接入方统一配置 |
| 补链 | 标识缺失时用什么组合字段兜底,结论怎么标注 | 平台侧建规则 |
定标识这一步最容易被简化成"用 UUID 就行"。技术上没错,但要注意两件:长度要统一,有的系统截断到 32 位,截断之后就对不上了;以及在跨系统传递时不要被当成敏感字段过滤掉。
落盘环节的坑在字段名和时区。同一个含义,有的系统写成 request_id,有的写成 traceId,有的写在日志正文里。日志平台做解析规则时得逐个适配,适配漏掉一个系统,这个系统的日志就参与不了串联。时区问题更隐蔽——不同设备输出的时间戳有的是本地时间、有的是 UTC,混在一起排序,一条链路的时间顺序会乱掉。
异步与定时任务这一段,最容易断
同步调用链上的透传,多数团队能处理。断点集中在两处。
一处是消息队列。生产者在发消息时把标识写进消息体,消费者取出后放进自己的处理上下文,这一步要在消费入口统一做,而不是让每个业务消费者各写一遍。写进消息体的好处是不依赖中间件特性,换组件也不用重做。
另一处是线程池与异步任务。主线程收到的标识不会自动传到工作线程,需要在提交任务时一并带入。这类问题在测试环境往往不出现——测试量小,异步用得少;上线之后并发上来,丢标识的比例也随之上升。
定时任务和批量作业没有入口标识,可行的替代方案是用批次号:每次调度生成一个批次标识,作业内所有子任务共用。它串不起"哪个用户触发的",但能串起"这一批做过什么",对于事后核对处理范围已经够用。
断链之后怎么补
断链不可能靠制度消除。所以平台侧要有一条兜底路径:用时间窗、账号、目标资产三个条件组合,把可能相关的记录圈出来。
这里有一条底线:补出来的关联必须标注为推断,不能和确定关联混在一起。一条日志记录到底属于哪一笔操作,是事实;根据时间和账号推测它属于哪一笔,是判断。两者在事后复盘、对外举证时的分量完全不同。把推断当事实写进报告,一旦被追问依据,整份材料都会被动。
补链规则也要定期复核。业务改造、系统替换之后,原来的组合条件可能已经失效,规则还在跑,圈出来的结果是错的。这类失效不会报错,只能靠抽样核对发现。
边界与前提
本文只谈日志侧的串联条件与落地动作——标识怎么定、怎么传、怎么落盘、断了怎么补,不谈调用链采样策略、探针部署方式,也不谈应用性能监测侧的链路追踪实现。文中提到的字段长度、抽样频次属一般性建议,具体以本项目现网系统清单与实测结果为准。
这件事的技术难度不高,难在跨系统推动:每个系统都要改一处代码,每个团队都觉得这一处不重要。深圳市奇摩计算机有限公司在做日志平台实施时,会把四件事做成一张对照表,逐系统勾,没勾上的系统在覆盖报告里单独列出,而不是笼统写一句"已完成接入"。这类清单如果要先搭一版,可预约咨询。
