本文档用于记录 GoFrame 重构时建议引入的监控、日志、链路追踪和采集技术栈,方便后续回看和落地。
| 组件 | 简单理解 | 主要用途 |
|---|---|---|
| Prometheus | 看指标 | 采集和存储 QPS、耗时、失败率、队列积压等数字指标 |
| Loki | 查日志 | 存储和检索应用日志、支付回调日志、异常日志 |
| Tempo | 查链路 | 查看一次请求从入口到 DB、Redis、外部接口的完整调用过程 |
| Grafana | 统一看板 | 在一个界面里看指标、日志、链路和告警 |
| OpenTelemetry | 统一埋点标准 | 规定应用如何输出 metrics、logs、traces |
| Alloy | 统一采集器 | 收集日志、指标、链路数据,再转发给 Prometheus、Loki、Tempo |
GoFrame API / Worker / Nginx / Redis / MySQL
|
| 产生 metrics / logs / traces
v
Grafana Alloy / OpenTelemetry Collector
|
+--> Prometheus 存指标
+--> Loki 存日志
+--> Tempo 存链路
|
v
Grafana 统一展示、查询、告警
这套体系要解决的问题不是“做一个漂亮大屏”,而是让线上问题能快速回答:
order_no、trace_id、channel 相关日志在哪里?Prometheus 负责存储数字型监控指标,适合做趋势、告警和服务健康判断。
在当前项目中建议重点采集:
| 指标 | 示例 |
|---|---|
| API 请求量 | 每个接口每分钟请求数 |
| API 耗时 | P50、P95、P99 延迟 |
| API 错误率 | 按 route、code、appid 聚合 |
| 支付回调 | 成功数、失败数、验签失败数、重复回调数 |
| CP 通知 | 成功数、失败数、重试次数 |
| Redis Stream | pending 数、lag、消费失败数 |
| MySQL | 连接池使用量、慢查询数量、事务失败数 |
| 外部接口 | 实名、支付、渠道 SDK 的耗时和失败率 |
典型告警:
5 分钟内支付回调失败率 > 5%
Redis Stream pending > 1000
CP 通知连续失败 > 20 次
接口 P95 延迟 > 800ms
某渠道登录失败率突然升高
注意:Prometheus 不适合当订单账本,支付金额、订单状态、发货状态必须以 MySQL 为准。
官方文档:https://prometheus.io/docs/introduction/overview/
Loki 负责日志存储和查询,适合定位具体问题。
GoFrame 日志建议输出 JSON,统一字段:
{
"time": "2026-06-09T14:30:00+08:00",
"level": "error",
"trace_id": "trace-xxx",
"request_id": "req-xxx",
"route": "/api/pay/notify",
"appid": "10001",
"user_id": 123,
"order_no": "P20260609xxx",
"channel": "wxpay",
"error_code": "PAY_SIGN_INVALID",
"message": "pay notify verify failed"
}
建议作为 Loki label 的字段:
service
env
level
route
channel
不建议作为 label 的字段:
order_no
user_id
request_id
trace_id
mobile
id_card
这些字段数量太多,放进日志内容里查询即可,避免 Loki label 爆炸。
当前项目最该记录的日志:
官方文档:https://grafana.com/docs/loki/latest/
Tempo 负责分布式链路追踪。它关心一次请求内部经历了哪些步骤,每一步耗时多少,哪里失败。
支付回调链路示例:
HTTP POST /pay/notify
-> parse request
-> verify payment sign
-> query order
-> check amount
-> update order paid
-> write member asset log
-> XADD Redis Stream
-> worker consume
-> notify CP
每一步都可以是一个 span。未来排查订单时,可以通过 trace_id 找到整条链路。
第一版建议接入的 trace 链路:
Tempo 不需要像日志一样保存大量文本,它主要保存 trace/span 信息。
官方文档:https://grafana.com/docs/tempo/latest/
Grafana 是统一查询和展示入口。Prometheus、Loki、Tempo 都可以接到 Grafana 里。
建议第一版做这些 Dashboard:
| Dashboard | 内容 |
|---|---|
| API 总览 | 请求量、错误率、P95/P99、Top 慢接口 |
| 支付总览 | 下单数、回调数、成功率、失败原因、渠道分布 |
| CP 通知 | 通知成功率、失败列表、重试次数、积压数 |
| complex 渠道 | 各渠道登录/支付成功率、失败率、耗时 |
| Redis Stream | stream 长度、pending、consumer lag |
| MySQL | 连接池、慢查询、错误数 |
| 日志检索 | 按 order_no、trace_id、channel 查询 |
Grafana 还可以配置告警,例如:
支付回调失败率升高 -> 钉钉/企业微信告警
Redis Stream 积压 -> 告警
CP 通知失败持续增长 -> 告警
某渠道登录失败率异常 -> 告警
官方文档:https://grafana.com/docs/grafana/latest/introduction/
OpenTelemetry 是标准,不是存储系统。
它负责定义应用如何输出:
metrics 指标
logs 日志
traces 链路
使用 OpenTelemetry 的好处:
GoFrame 重构时建议从一开始就设计这些上下文字段:
trace_id
request_id
appid
user_id
game_id
order_no
channel
route
官方文档:https://opentelemetry.io/docs/what-is-opentelemetry/
Grafana Alloy 是采集器,可以理解为“观测数据中转站”。
它可以采集:
然后转发到:
Prometheus
Loki
Tempo
Grafana Cloud
在当前项目里,Alloy 可以负责:
采集 GoFrame JSON 日志 -> 发给 Loki
采集 OpenTelemetry trace -> 发给 Tempo
采集应用 metrics -> 发给 Prometheus
采集 Nginx 日志 -> 发给 Loki
官方文档:https://grafana.com/docs/alloy/latest/
不要一次性把所有东西都做复杂,建议分阶段。
目标:能看到接口和支付的关键指标。
必须有:
目标:能按订单、渠道、trace_id 查日志。
必须统一日志字段:
trace_id
request_id
route
appid
user_id
order_no
channel
error_code
目标:核心链路能追踪。
优先接:
| 当前痛点 | 这套技术栈的帮助 |
|---|---|
| 支付失败难排查 | 指标看失败率,日志查订单,链路看卡点 |
| 渠道太多 | 按 channel 聚合成功率、失败率、耗时 |
| CP 通知不稳定 | Redis Stream 指标 + 日志 + 重试链路 |
| 老代码逻辑分散 | 通过 trace_id 把一次业务请求串起来 |
| 问题发现太晚 | Prometheus/Grafana 告警提前发现 |
| 日志散落 | Loki 统一查询 |
第一版不追求全量完美,建议至少做到:
Prometheus:接口指标、支付指标、Redis Stream 指标
Loki:GoFrame JSON 日志、Nginx 日志
Grafana:API、支付、渠道、队列四个 Dashboard
OpenTelemetry:生成 trace_id,并在日志里透传
Tempo:先只接支付回调和 CP 通知链路
Alloy:统一采集日志和 trace
这样就能覆盖重构初期最核心的风险:接口异常、支付异常、渠道异常、队列积压、发货失败。