一、日志体系概述:为什么做市系统需要日志?
做市系统,说白了就是一台高速运转的印钞机——但也可能是一台碎钞机。
我见过太多团队,系统上线时意气风发,出问题时手忙脚乱。为什么?因为没有日志。你想想看,一个每秒处理上千笔订单的系统,突然亏了几百万,你连刚才发生了什么都不知道,这多可怕。
所以今天咱们聊聊日志。不是那种随便打印几行信息的日志,而是真正能救命的日志体系。
1.1 做市系统为什么离不开日志?
先问个问题:做市系统和普通交易系统,对日志的要求有什么不同?
答案是——做市系统对日志的要求高得多。原因有三:
- 高频:每秒成百上千笔订单,没有日志你根本不知道系统在干什么
- 复杂:做市策略涉及报价、对冲、风控多个模块,一个环节出问题就全崩
- 资金敏感:一个bug可能几分钟就亏掉几十万,必须快速定位
我记得有一次,我们团队上线了一套新的做市策略。运行了大概两个小时,突然发现账户亏了50万。所有人慌了,但因为没有日志,谁也不知道问题出在哪。后来花了整整三天才找到原因——一个报价计算的精度问题。
从那以后,我定了个规矩:没有日志的代码,不允许上线。
1.2 日志的三大目标
做市系统的日志,不是随便打几个print就完事了。它需要达成三个核心目标:可观测性、可追溯性、可审计性。
1.2.1 可观测性:你得知道系统在干什么
可观测性,说白了就是系统运行时的「仪表盘」。你不需要登录服务器看日志文件,就能知道系统状态。
我个人的习惯是,每个关键模块都要输出以下信息:
- 当前报价状态(买价、卖价、数量)
- 持仓变化(每次成交后的持仓更新)
- 风险指标(敞口、保证金、盈亏)
- 异常事件(连接断开、超时、拒绝)
关键点:可观测性不是让你看原始日志,而是通过日志聚合出有意义的指标。
举个例子,我们会在日志中输出这样的结构化信息:
{
"timestamp": "2024-01-15T10:30:00.123Z",
"module": "quote_engine",
"event": "quote_update",
"symbol": "BTC-USDT",
"bid_price": 42000.50,
"ask_price": 42001.00,
"bid_size": 1.5,
"ask_size": 1.5,
"spread": 0.50
}
这种结构化的日志,可以直接接入Grafana或者Kibana,实时展示报价变化。我曾经用这种方式,在五分钟内定位到一个报价延迟的问题——因为日志里记录了每次报价的时间戳,一对比就发现某个交易所的行情推送慢了200毫秒。
1.2.2 可追溯性:出了问题能查回去
可追溯性,就是「事后诸葛亮」的能力。系统出问题了,你能顺着日志一路查回去,找到根因。
这里有个避坑指南:我曾经犯过一个错误,就是日志只记录最终结果,不记录中间过程。结果有一次系统报了个奇怪的错误,我查了半天日志,只看到「订单提交失败」,但不知道失败的原因是什么。
后来我改了策略:每个关键操作都要记录「输入-处理-输出」三个阶段的日志。
| 阶段 | 日志内容 | 示例 |
|---|---|---|
| 输入 | 收到什么指令 | 收到报价请求,参数:symbol=BTC-USDT, side=buy, price=42000 |
| 处理 | 做了什么计算 | 计算最优报价,考虑库存成本,调整价差 |
| 输出 | 最终结果是什么 | 提交订单:id=12345, price=42000.50, qty=1.0 |
这样做的好处是,你可以在日志里完整还原一个请求的生命周期。嗯,这里要注意:每个请求都要有一个唯一的trace_id,这样才能把分散在不同模块的日志串起来。
1.2.3 可审计性:合规和风控的底线
可审计性,听起来很官方,但做市系统真的离不开它。为什么?
第一,交易所会查你。你想想看,交易所每天处理那么多交易,如果出现异常交易,他们第一个查的就是做市商。没有完整的日志,你连自证清白都做不到。
第二,内部风控需要。我们团队每周都会做一次交易复盘,看看有没有违规操作。比如某个交易员是不是在非交易时间下了单,或者报价是不是超出了风控限制。
可审计性要求日志满足三个条件:
- 不可篡改:日志一旦写入,就不能被修改或删除
- 完整记录:所有操作都要记录,不能有遗漏
- 长期保存:根据监管要求,一般需要保存5-7年
警告:千万不要把日志存在数据库里!数据库可能被篡改。我建议使用专门的日志系统,比如ELK或者Loki,并且开启日志的写保护。
1.3 日志体系的核心架构
说了这么多,咱们来看看一个完整的日志体系长什么样。下面这张图是我自己设计的做市系统日志架构:
这个架构图展示了日志从产生到应用的完整链路。你想想看,如果没有这个体系,日志就是一堆散落的文件,根本发挥不了作用。
1.4 日志体系的设计原则
最后,分享几个我这些年总结的日志设计原则:
- 结构化优先:不要打纯文本日志,用JSON格式。这样方便机器解析和查询。
- 分级管理:DEBUG、INFO、WARN、ERROR四级,生产环境只开INFO及以上。
- 上下文关联:每个日志都要带上trace_id、module、timestamp等上下文信息。
- 性能第一:日志不能影响主流程。我建议用异步写入,或者用消息队列缓冲。
- 定期清理:日志不是越多越好。设置合理的保留周期,比如热数据7天,冷数据1年。
小技巧:我个人习惯在代码里用装饰器或者AOP来自动记录日志,而不是在每个函数里手动写。这样既统一格式,又减少遗漏。
好了,日志体系的概念就讲到这里。记住一句话:没有日志的做市系统,就像没有黑匣子的飞机——你永远不知道它什么时候会出事,出了事也不知道为什么。
下一节,咱们会深入聊聊日志的具体实现,包括怎么设计日志格式、怎么选择日志框架、怎么保证日志性能。这些都是实战中会遇到的硬骨头。