3. 日志格式规范:标准日志格式定义、字段映射与日志级别
做市系统的日志,说白了就是系统的「黑匣子」。
我见过太多团队,日志写得随心所欲。出问题的时候,一堆文本堆在那里,根本没法快速定位。你想想看,每秒几万笔订单的系统,日志要是乱写,排查问题就像大海捞针。
所以,这一节我们来聊聊日志格式的规范化。我个人习惯,先把标准定死,后面所有模块都按这个来。这样不管是做性能分析,还是事后复盘,都能事半功倍。
3.1 标准日志格式定义
先给个结论:一条好的日志,应该让机器能解析,让人能看懂。
我推荐使用 JSON 格式。为什么?因为结构化。你想想,如果用纯文本,字段之间用空格或逗号分隔,一旦某个字段里包含了分隔符,解析就崩了。JSON 天生就解决了这个问题。
下面是我在项目中沉淀下来的标准格式模板:
{
"timestamp": "2025-03-21T14:30:00.123456+08:00",
"level": "INFO",
"module": "order_manager",
"thread": "order-worker-12",
"message": "订单已提交至交易所",
"fields": {
"order_id": "ORD2025032100012345",
"symbol": "BTC-USDT",
"side": "BUY",
"price": 67500.12,
"quantity": 0.15,
"status": "NEW"
},
"context": {
"session_id": "SESS_ABC123",
"strategy_id": "STRAT_MM_001",
"exchange": "BINANCE"
}
}
嗯,这里要注意几个关键点:
- timestamp:必须带时区,精确到微秒。做市系统里,微秒级的差异可能就是盈亏的分水岭。
- level:日志级别,后面会细讲。
- module:哪个模块产生的日志。比如 order_manager、risk_control、market_data。
- fields:核心业务字段,这是分析的重点。
- context:上下文信息,方便串联一次完整的交易流程。
核心原则:每条日志都应该能独立还原一个事件的全貌。不要依赖前后文去推断。
3.2 字段映射:从业务到日志
字段映射,说白了就是把业务数据「翻译」成日志字段。我见过最坑的情况是,日志里只记了个订单ID,结果订单ID本身是自增的,根本没法关联到具体策略。你说这怎么查?
下面这张表,是我认为做市系统日志里必须包含的核心字段:
| 字段名 | 类型 | 说明 | 示例 |
|---|---|---|---|
| order_id | string | 全局唯一订单ID,建议用雪花算法生成 | ORD2025032100012345 |
| symbol | string | 交易对 | BTC-USDT |
| side | string | 买卖方向 | BUY / SELL |
| price | double | 委托价格,保留交易所支持的最大精度 | 67500.12 |
| quantity | double | 委托数量 | 0.15 |
| status | string | 订单状态,枚举值 | NEW / PARTIALLY_FILLED / FILLED / CANCELED / REJECTED |
| filled_qty | double | 已成交数量 | 0.10 |
| filled_avg_price | double | 成交均价 | 67501.00 |
| latency_us | int64 | 从生成到确认的延迟,单位微秒 | 1523 |
这里我特别想强调一下 latency_us 这个字段。做性能调优,没有延迟数据就是盲人摸象。我在项目中要求每个订单的生命周期都要记录时间戳,从生成、发送、确认到成交,每个环节的耗时都要能算出来。
小技巧:订单状态建议用枚举值,不要用中文。比如用 NEW 而不是「新建」。这样在日志分析工具里做过滤和聚合会方便很多。
3.3 日志级别:INFO / WARN / ERROR
日志级别怎么定?很多团队就三个级别:INFO、WARN、ERROR。但实际用起来,经常是 INFO 满天飞,WARN 没人看,ERROR 又不够用。
我个人习惯,做市系统的日志级别可以这样划分:
- INFO:记录正常的业务流程。比如订单创建、成交、撤单。这些日志用于日常监控和事后复盘。
- WARN:表示系统遇到了异常情况,但还能继续运行。比如网络抖动导致重连、订单部分成交但未完全成交、价格偏离预期阈值。
- ERROR:表示系统无法正常处理某个请求。比如订单被交易所拒绝、数据库写入失败、风控检查未通过。
我曾经犯过一个错误:把所有异常都打成了 ERROR。结果每天 ERROR 日志上万条,真正需要关注的严重问题反而被淹没了。后来我定了个规矩:只有影响资金安全或系统稳定性的问题,才打 ERROR。
避坑指南:我曾经在日志里把「订单被部分成交」打成了 ERROR。结果运维半夜被报警吵醒,跑过来一看,只是正常的市场波动。从那以后,我要求所有日志级别必须和告警策略联动。WARN 级别的日志,只记录,不告警。ERROR 级别的日志,才触发告警。
3.4 知识体系结构图
下面这张图,把日志格式规范的核心逻辑串起来了。从原始业务数据,到标准化的日志输出,再到不同级别的分类,最终服务于性能分析和问题排查。
这张图其实就讲了三件事:数据从哪里来、怎么格式化、怎么分类。你按照这个结构去设计日志系统,基本不会出大问题。
3.5 实战建议
最后,给几个我在实战中踩过的坑和总结的经验:
- 日志不要打太多:INFO 级别的日志,每秒不要超过 1000 条。否则磁盘 I/O 会成为瓶颈。我见过一个系统,每秒打 5 万条日志,结果日志系统先挂了。
- 敏感信息脱敏:API Key、私钥、用户手机号,这些绝对不能出现在日志里。我曾经在日志里不小心打印了交易所的 API Secret,还好发现得早,不然就出大事了。
- 日志轮转要配置好:按天轮转,保留 30 天。做市系统的日志量很大,不轮转的话,磁盘很快就会被撑爆。
- 统一日志库:整个团队用同一个日志库,同一个配置。不要这个模块用 log4j,那个模块用 logback,排查问题的时候会疯掉。
我的习惯:每次上线新策略,我都会先跑一遍「日志完整性测试」。就是模拟一笔完整的交易,然后去日志里查,看每个环节的日志是不是都打了,字段是不是都对了。这个习惯帮我避免了好几次线上事故。
好了,日志格式规范就讲到这里。记住一句话:日志是系统的第一道防线。写好了,排查问题事半功倍;写不好,再牛的分析工具也救不了你。