第一章:日志体系概述——为什么交易系统需要日志?
大家好,我是老张。在量化交易这个行当摸爬滚打了十来年,今天咱们聊聊日志。
你可能觉得日志不就是print一下嘛?说实话,我刚开始做交易系统时也这么想。直到有一次,凌晨三点,策略突然跑飞了,我看着满屏的报错,愣是找不到问题出在哪。那感觉,就像在黑暗里找一只黑猫,而且猫还不一定在屋里。
从那以后,我养成了一个习惯:日志就是交易系统的黑匣子。飞机有黑匣子,交易系统也得有。没有日志,你连死都不知道怎么死的。
1.1 交易系统为什么需要日志?
你想想看,交易系统跟普通Web应用最大的区别是什么?
钱在动,而且动得很快。
一个订单从发出到成交,可能就几毫秒。这中间任何一个环节出问题,轻则丢单,重则穿仓。我见过最惨的一次,就因为日志没打全,排查问题花了整整两天,那两天里策略是停着的,损失了多少?嗯,不提了。
具体来说,日志在交易系统里有这几个核心作用:
- 问题定位:系统崩了,日志是第一现场。没有日志,你只能靠猜。
- 性能分析:订单处理延迟了多少?网络抖动了几次?日志里全有。
- 合规审计:监管要查你的交易记录,你拿什么给?日志。
- 复盘优化:策略为什么亏了?回测数据不够,得看实盘日志。
- 告警触发:系统异常了,日志级别一升,告警就来了。
核心观点:日志不是写给机器看的,是写给未来的自己看的。你半夜被叫起来排查问题时,会感谢那个认真打日志的自己。
1.2 日志的黄金法则:5W1H
我刚开始带团队时,发现大家打日志很随意。有人只打"error",有人只打"success"。排查问题?全靠脑补。
后来我定了个规矩:每条日志都要回答6个问题。这就是5W1H法则。
| 要素 | 含义 | 交易系统示例 |
|---|---|---|
| Who | 谁触发的? | 用户ID、策略ID、交易员 |
| What | 发生了什么? | 下单、撤单、成交、报错 |
| When | 什么时间? | 精确到毫秒的时间戳 |
| Where | 发生在哪个模块? | 订单网关、风控引擎、行情模块 |
| Why | 为什么会发生? | 资金不足、网络超时、价格异常 |
| How | 结果如何? | 成功/失败、耗时、返回码 |
举个例子,一条合格的日志应该是这样的:
2024-01-15 14:30:22.456 | INFO | OrderGateway | user=10086 |
下单成功 | symbol=BTC-USDT | price=45000.12 | qty=0.5 |
耗时=12ms | order_id=ORD202401150001
你看,这一条日志里,谁、什么、什么时候、在哪、为什么、结果如何,全有了。出了问题,一眼就能定位。
我的习惯:每条日志都带上请求ID(trace_id),这样就能把一次交易的全链路串起来。从用户点击到订单成交,中间经过多少个服务,每个服务花了多少时间,一目了然。
1.3 日志级别的选择策略
日志级别这事儿,看似简单,其实坑很多。我见过有人把所有日志都打成INFO,结果一天几个TB,磁盘直接爆了。也见过有人只打ERROR,结果排查问题时啥线索都没有。
咱们一个一个说。
DEBUG
什么时候用:开发调试、排查疑难杂症时用。说白了,就是给开发人员看的。
什么时候关:生产环境默认关闭。除非你在排查特定问题,否则别开。我曾经在生产环境开了DEBUG,结果日志量暴涨100倍,把ES集群打挂了。嗯,血的教训。
INFO
什么时候用:记录系统正常运行的关键节点。比如订单创建成功、成交回报到达、策略启动完成。
注意:别啥都打INFO。我见过有人把每次循环都打INFO,那跟DEBUG有啥区别?
WARN
什么时候用:系统还能跑,但有点不对劲。比如网络重连、风控阈值接近、行情延迟偏高。
我的建议:WARN是预警信号,别忽视。很多大事故,都是从WARN开始的。
ERROR
什么时候用:系统出错了,但还能继续运行。比如下单失败、数据库连接超时、某个策略异常退出。
注意:ERROR一定要带堆栈信息,不然你都不知道错在哪。
FATAL
什么时候用:系统彻底挂了,无法继续运行。比如内存溢出、核心进程崩溃、数据库不可用。
我的经验:FATAL级别的日志,一定要触发告警,而且是最高级别的告警。电话、短信、钉钉,全给我响起来。
避坑指南:我曾经遇到过一个同事,把所有异常都打成FATAL。结果FATAL日志一天几千条,真正的致命问题反而被淹没了。记住:FATAL是核弹,别当鞭炮用。
1.4 日志级别选择矩阵
为了方便大家记忆,我整理了一个矩阵。你写日志时,对着这个表选级别就行。
| 场景 | 推荐级别 | 说明 |
|---|---|---|
| 正常业务流程 | INFO | 记录关键节点,别太频繁 |
| 异常但可恢复 | WARN | 比如重试、降级 |
| 业务失败 | ERROR | 带上下文和堆栈 |
| 系统崩溃 | FATAL | 立即告警 |
| 调试信息 | DEBUG | 生产环境慎用 |
| 性能数据 | INFO | 建议单独日志文件 |
1.5 日志体系的核心逻辑
说了这么多,咱们用一张图来总结一下。这张图是我自己画的,展示了日志体系的核心逻辑。
这张图其实就说了三件事:从哪来、怎么写、往哪去。日志来源五花八门,但经过5W1H的规范,再配上合适的级别,最后输出到统一的地方。这样,你的日志体系才算完整。
最后说一句:日志这事儿,前期多花点心思,后期能省很多事。我见过太多团队,系统上线了才想起来补日志,那叫一个痛苦。所以,从一开始就把日志体系搭好,别偷懒。