15、日志与监控:日志系统搭建、实时监控面板、告警通知(邮件/微信)、性能指标采集
做市系统跑起来之后,你最怕什么?
我最怕半夜手机突然响了——不是告警,而是交易员打电话说「系统好像不动了」。你想想看,等你打开电脑连上VPN,再翻日志,黄花菜都凉了。
所以这一章,咱们就把日志和监控彻底搞定。说白了,就是给系统装上「黑匣子」和「仪表盘」。
15.1 日志系统搭建:别再用 print 了
我见过不少新手,调试时用 print,上线了还留着 print。这在做市系统里是致命的——print 没有级别,没有时间戳,没有轮转,跑几天磁盘就满了。
我个人习惯用 Python 的 loguru,比标准 logging 好用十倍。安装就一行:
pip install loguru
然后配置一个全局日志器:
from loguru import logger
import sys
# 移除默认 handler
logger.remove()
# 添加控制台输出(开发用)
logger.add(sys.stderr, level="DEBUG", format="{time} | {level} | {message}")
# 添加文件输出(生产用)
logger.add(
"logs/做市系统_{time:YYYY-MM-DD}.log",
rotation="1 day", # 每天轮转
retention="30 days", # 保留30天
compression="zip", # 压缩旧日志
level="INFO",
format="{time} | {level} | {name}:{function}:{line} | {message}"
)
这里有个关键点:日志级别要分清楚。DEBUG 记录细节,INFO 记录正常流程,WARNING 记录异常但可恢复的情况,ERROR 记录需要人工介入的问题。
15.2 实时监控面板:Grafana + Prometheus
日志是事后查的,监控面板是实时看的。我推荐用 Prometheus 采集指标,Grafana 展示面板。这套组合在量化圈几乎是标配。
先看整体架构:
在代码里暴露 Prometheus 指标,我习惯用 prometheus_client 库:
from prometheus_client import start_http_server, Gauge, Counter, Histogram
import random
import time
# 定义指标
order_counter = Counter('orders_total', '总订单数', ['symbol', 'side'])
position_gauge = Gauge('position_size', '当前持仓量', ['symbol'])
latency_histogram = Histogram('order_latency_seconds', '订单延迟分布', buckets=[0.001, 0.005, 0.01, 0.05, 0.1])
# 启动 HTTP 服务(Prometheus 会来抓取)
start_http_server(8000)
# 在交易逻辑中更新指标
def on_order_filled(order):
order_counter.labels(symbol=order.symbol, side=order.side).inc()
position_gauge.labels(symbol=order.symbol).set(order.position)
latency_histogram.observe(order.latency)
- 订单延迟:从发单到成交的时间,超过100ms就要警惕
- 成交率:已成交订单 / 总发单数,太低说明报价策略有问题
- 库存敞口:当前持仓偏离目标的程度,超过阈值要触发对冲
- 系统资源:CPU、内存、网络延迟,防止硬件瓶颈
15.3 告警通知:邮件 + 微信
光有面板不够,你不可能24小时盯着屏幕。告警才是最后的防线。
我曾经有一次,因为交易所API改了字段格式,系统连续报错半小时我才发现。从那以后,我给自己定了个规矩:任何ERROR级别的日志,必须通知到手机。
邮件告警用 smtplib 就能搞定:
import smtplib
from email.mime.text import MIMEText
def send_email_alert(subject, body):
msg = MIMEText(body, 'plain', 'utf-8')
msg['Subject'] = f'[做市系统告警] {subject}'
msg['From'] = 'alert@yourdomain.com'
msg['To'] = 'ops@yourdomain.com'
with smtplib.SMTP('smtp.yourdomain.com', 587) as server:
server.login('alert@yourdomain.com', 'password')
server.send_message(msg)
微信通知稍微麻烦点。我推荐用 企业微信机器人,免费且稳定。建一个群,添加机器人,拿到 Webhook URL:
import requests
import json
def send_wechat_alert(message):
url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的KEY"
data = {
"msgtype": "text",
"text": {
"content": f"⚠️ 做市系统告警\n{message}"
}
}
requests.post(url, json=data)
- P0(紧急):系统宕机、资金异常 → 微信 + 电话
- P1(重要):订单延迟飙升、成交率骤降 → 微信
- P2(一般):某个交易所连接断开 → 邮件
- P3(通知):每日成交统计、收益报告 → 邮件
15.4 性能指标采集:别等出事了再查
性能指标是「预防性」的。等用户说系统卡了,再去看指标就晚了。我习惯每5秒采集一次系统级指标:
import psutil
import time
def collect_system_metrics():
while True:
cpu_percent = psutil.cpu_percent(interval=1)
memory_percent = psutil.virtual_memory().percent
net_io = psutil.net_io_counters()
# 上报到 Prometheus
system_cpu_gauge.set(cpu_percent)
system_memory_gauge.set(memory_percent)
system_network_bytes_gauge.set(net_io.bytes_sent + net_io.bytes_recv)
time.sleep(5)
除了系统指标,业务指标更重要。我建议至少采集这些:
| 指标名称 | 类型 | 说明 | 告警阈值 |
|---|---|---|---|
| 订单处理延迟 | Histogram | 从收到行情到发出订单的时间 | P99 > 50ms |
| 交易所连接状态 | Gauge | 0=断开, 1=连接 | 0 持续10秒 |
| 订单簿深度 | Gauge | 买卖各档位的挂单量 | 某档位为0 |
| 资金余额 | Gauge | 各币种可用余额 | 低于安全线 |
| 网络丢包率 | Gauge | 与交易所之间的网络质量 | > 1% |
15.5 整合:一个完整的监控循环
把上面这些串起来,就是一个完整的闭环:
- 采集层:loguru 写日志,Prometheus client 暴露指标
- 存储层:日志存文件(按天轮转),指标被 Prometheus 拉取存储
- 展示层:Grafana 连接 Prometheus,画出实时面板
- 告警层:Grafana 或 Prometheus 触发告警规则,发邮件/微信
- 响应层:收到告警后,查日志定位问题,修复后恢复
嗯,这套体系搭好之后,我晚上睡觉踏实多了。手机偶尔响一下,看一眼告警内容,心里就有数——是哪个模块出了问题,严重不严重,要不要爬起来处理。
说白了,日志和监控不是为了「好看」,而是为了让你在出问题的时候,能比别人快5分钟定位到根因。这5分钟,可能就是几万块钱的差距。
无相订单流研究社 微信Lucian808555