10、监控与告警系统:Prometheus + Grafana 指标采集,日志聚合(ELK Stack),业务告警规则设计
做量化交易系统,最怕什么?
怕半夜三点系统崩了,你还在睡觉。怕策略跑偏了,亏了一晚上你才发现。怕日志堆成山,出了事根本不知道从哪查起。
我做了这么多年做市商系统,可以负责任地告诉你:监控和告警,比策略本身还重要。策略亏钱可以改,系统崩了没发现,那才是真灾难。
这一章,我们就来聊聊怎么把监控体系搭起来。说白了,就是三件事:指标采集、日志聚合、告警规则。
10.1 为什么需要三层监控?
我个人习惯把监控分成三层:
- 基础设施层:CPU、内存、磁盘、网络。这些挂了,啥都别谈。
- 应用层:订单处理延迟、撮合成功率、WebSocket 连接数。这些是系统的「心跳」。
- 业务层:持仓盈亏、资金费率、敞口风险。这些直接关系到赚不赚钱。
你想想看,如果只盯着业务层,服务器磁盘满了你都不知道。反过来,只看基础设施,策略跑偏了你也发现不了。三层都得看。
我在项目中遇到过最坑的一次:服务器 CPU 负载正常,内存也够,但订单处理延迟从 2ms 飙到了 500ms。为什么?因为网卡队列被某个日志进程占满了。如果只看 CPU 和内存,你永远找不到原因。
10.2 Prometheus + Grafana:指标采集与可视化
Prometheus 这东西,说白了就是一个时序数据库。它每隔几秒去拉一次数据,存下来,然后 Grafana 负责画图。
10.2.1 暴露指标端点
你的交易系统需要暴露一个 /metrics 接口,Prometheus 会来抓。我一般用 Python 的 prometheus_client 库,几行代码搞定:
from prometheus_client import start_http_server, Gauge, Counter, Histogram
import random
import time
# 定义指标
order_latency = Histogram('order_latency_seconds', '订单处理延迟', buckets=[0.001, 0.005, 0.01, 0.05, 0.1])
open_orders = Gauge('open_orders_total', '当前挂单数量')
trade_volume = Counter('trade_volume_usdt_total', '累计交易量', ['symbol'])
# 模拟业务逻辑
def process_order():
with order_latency.time():
time.sleep(random.uniform(0.001, 0.05))
open_orders.set(random.randint(0, 100))
trade_volume.labels(symbol='BTCUSDT').inc(random.uniform(100, 1000))
if __name__ == '__main__':
start_http_server(8000) # 暴露 /metrics 端口
while True:
process_order()
time.sleep(1)
10.2.2 Prometheus 配置
配置文件 prometheus.yml 里,告诉它去哪抓数据:
scrape_configs:
- job_name: 'market_maker'
scrape_interval: 5s
static_configs:
- targets: ['localhost:8000']
嗯,这里要注意:scrape_interval 别设太短,5秒足够了。太频繁反而增加系统开销。
10.2.3 Grafana 仪表盘
Grafana 这边,我习惯建三个 Dashboard:
- 系统概览:CPU、内存、网络、磁盘 IO
- 交易监控:订单延迟分布、挂单数量、成交笔数
- 风控看板:敞口、盈亏、资金费率
每个 Dashboard 配上告警阈值,比如「订单延迟 P99 超过 100ms」就标红。
10.3 ELK Stack:日志聚合与分析
指标是数字,日志是文字。两者缺一不可。
ELK 就是 Elasticsearch + Logstash + Kibana。流程很简单:
- Logstash 收集日志,解析成结构化数据
- Elasticsearch 存起来,支持全文搜索
- Kibana 负责展示和查询
10.3.1 日志格式规范
我要求团队所有日志必须用 JSON 格式。为什么?因为 Logstash 解析 JSON 最方便,而且字段清晰。
{
"timestamp": "2025-01-15T10:30:00.123Z",
"level": "ERROR",
"module": "order_executor",
"message": "订单提交失败",
"order_id": "ORD123456",
"error_code": "INSUFFICIENT_BALANCE",
"latency_ms": 45
}
10.3.2 Logstash 配置示例
input {
beats {
port => 5044
}
}
filter {
json {
source => "message"
}
date {
match => ["timestamp", "ISO8601"]
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "market-maker-%{+YYYY.MM.dd}"
}
}
Logstash 的 filter 很强大。你可以用它做字段提取、类型转换、甚至数据脱敏。我个人习惯把 latency_ms 这种数值字段单独提取出来,方便在 Kibana 里做聚合分析。
10.4 业务告警规则设计
告警不是越多越好。告警太多,人会麻木,最后变成「狼来了」。
我总结了一套规则:只告警那些需要人干预的事情。系统自己能恢复的,别吵我。
10.4.1 告警分级
| 级别 | 响应时间 | 示例 |
|---|---|---|
| P0(致命) | 立即处理 | 系统宕机、数据库连接失败、持仓敞口超限 |
| P1(严重) | 15分钟内 | 订单延迟 > 500ms、WebSocket 断连 |
| P2(警告) | 1小时内 | 磁盘使用率 > 80%、内存使用率 > 90% |
| P3(通知) | 次日处理 | 日志中出现异常模式、交易量异常波动 |
10.4.2 Prometheus 告警规则
在 alert.rules.yml 里定义:
groups:
- name: market_maker_alerts
rules:
- alert: HighOrderLatency
expr: histogram_quantile(0.99, rate(order_latency_seconds_bucket[5m])) > 0.1
for: 2m
labels:
severity: P1
annotations:
summary: "订单延迟 P99 超过 100ms"
description: "当前延迟 {{ $value }}s"
- alert: OpenOrdersTooHigh
expr: open_orders_total > 500
for: 1m
labels:
severity: P2
annotations:
summary: "挂单数量超过 500"
这里有个细节:for: 2m 表示持续 2 分钟才触发告警。为什么要加这个?因为瞬时抖动很正常,持续异常才需要处理。我刚开始做的时候没加这个,结果半夜被瞬时的网络抖动吵醒了好几次。
10.4.3 告警通知渠道
Alertmanager 支持多种通知方式。我个人推荐:
- P0/P1:电话 + 短信 + 企业微信/钉钉
- P2:企业微信/钉钉
- P3:邮件,第二天看就行
10.5 整体架构图
下面这张图,是我做监控系统时的标准架构。你可以照着搭:
10.6 实战建议
最后,给你几个我踩过坑之后总结的建议:
- 先搭监控,再写策略。没有监控的策略,就像闭着眼睛开车。
- 告警规则要迭代。刚开始可以松一点,慢慢收紧。别一上来就设一堆规则,你会被烦死的。
- 日志要保留至少 30 天。很多问题不是当天能发现的,需要回溯历史数据。
- 定期演练告警。我每季度会做一次「断网演练」,看看告警能不能正常触发,通知能不能正常收到。
交易系统化学习资料 微信Strategy888888