Level 38 / 阅读练习

生产环境日志、监控和告警

理解日志、指标、链路追踪、request_id、P95、慢查询和告警设计。

Progress

阅读中

0/2 步完成 / 阅读后完成练习才算通关

Practice

本关怎么过

  • 读完正文后确认完成阅读
  • 完成 1 道选择题练习
  • 答错时看解释,再回到正文补理解

一句话:日志、监控和告警就是给线上系统装上仪表盘和报警器,让你知道系统现在是不是健康,出问题时能快速找到原因。

本篇学完你会什么:知道线上系统应该看哪些指标、日志怎么打才有用、告警怎么设才不吵,以及一次接口变慢时应该按什么顺序排查。

1. 为什么上线后不能只看“服务还在”

本地开发时,你看到接口能返回,就会觉得它没问题。

上线后不一样。真实用户会同时访问,数据库会变大,网络会抖,第三方服务会超时。

一个服务“还活着”不代表它“好用”:

状态 用户感受 系统可能发生了什么
接口能返回 正常 服务健康
接口很慢 卡顿 数据库慢、外部接口慢、连接池不够
偶尔 500 不稳定 某些输入没处理、依赖偶发失败
大量 401/403 不能用 token 过期、权限配置错
CPU 很高 页面转圈 死循环、大查询、并发太高

所以线上系统至少要有三样东西:

日志:发生了什么事
监控:现在状态怎么样
告警:什么时候需要人处理

<!-- image-slot: production-observability-map; purpose: 展示日志、指标、追踪、告警之间的关系; alt: 生产环境可观测性结构图 -->

2. 日志、指标、链路追踪分别是什么

日志

日志像系统日记,记录某一刻发生了什么。

例子:

2026-06-30 10:20:31 INFO user login success user_id=12 request_id=abc123
2026-06-30 10:20:35 ERROR create order failed user_id=12 error=payment timeout request_id=abc123

日志适合回答:

刚才发生了什么?
哪个用户触发的?
报错堆栈是什么?
请求 id 是多少?

指标

指标像仪表盘,持续显示系统状态。

常见指标:

指标 含义
QPS 每秒有多少请求
P95 响应时间 95% 的请求在多久内完成
错误率 失败请求占比
CPU / 内存 服务器资源是否紧张
数据库连接数 连接池是否快被用完

链路追踪

链路追踪用来回答:

一个请求从前端到后端,再到数据库、Redis、第三方接口,中间每一步花了多久?

小项目可以先不接复杂 tracing,但至少要有 request_id。它能把同一次请求的多条日志串起来。

3. FastAPI 项目日志怎么打

日志不是越多越好,而是要能帮你排查问题。

建议每次请求都带上:

字段 作用
request_id 把同一次请求串起来
method GET、POST、PUT、DELETE
path 请求路径
status_code 响应状态码
duration_ms 花了多久
user_id 当前用户,没有就为空
error 错误类型和消息

一个简单中间件示例:

import time
import uuid
import logging

from fastapi import Request

logger = logging.getLogger("app.request")


async def request_log_middleware(request: Request, call_next):
    request_id = request.headers.get("X-Request-Id") or str(uuid.uuid4())
    start = time.perf_counter()

    try:
        response = await call_next(request)
    except Exception:
        duration_ms = round((time.perf_counter() - start) * 1000, 2)
        logger.exception(
            "request failed",
            extra={
                "request_id": request_id,
                "method": request.method,
                "path": request.url.path,
                "duration_ms": duration_ms,
            },
        )
        raise

    duration_ms = round((time.perf_counter() - start) * 1000, 2)
    logger.info(
        "request finished",
        extra={
            "request_id": request_id,
            "method": request.method,
            "path": request.url.path,
            "status_code": response.status_code,
            "duration_ms": duration_ms,
        },
    )
    response.headers["X-Request-Id"] = request_id
    return response

还要把它注册到 FastAPI 应用里:

app.middleware("http")(request_log_middleware)

注意:extra={...} 里的字段不会自动出现在所有日志格式里。真实项目要配合 JSON logger,或者在 logging formatter 里明确输出 request_idpathduration_ms 这些字段。不然代码写了,日志平台里还是看不到。

大白话:每个请求都给一张小票。以后用户说“刚才失败了”,你可以用小票号找到完整过程。

4. 监控应该先看哪些指标

初学者不要一上来做几十个图。先看最能说明问题的 8 个:

指标 为什么重要
请求量 QPS 判断流量有没有突然变大
P95 响应时间 判断大部分用户是否卡
5xx 错误率 判断服务是否异常
4xx 比例 判断参数、鉴权、权限问题是否变多
CPU 判断计算资源是否紧张
内存 判断是否有泄漏或缓存过大
数据库慢查询 判断瓶颈是否在 SQL
Redis 命中率 判断缓存是否有效

推荐先按页面或接口分组:

/api/v1/auth/login
/api/v1/users
/api/v1/knowledge/search

不要只看全站平均值。平均值很容易把某个接口的慢问题藏起来。

5. 告警怎么设才有用

告警的目标不是“声音越大越专业”,而是让人及时处理真正的问题。

好的告警应该有:

内容 示例
触发条件 5xx 错误率 5 分钟内超过 2%
影响范围 /api/v1/orders 接口
当前数值 当前错误率 8.5%
排查入口 日志查询链接、监控面板链接
处理建议 先看最近发布、数据库、第三方接口

不建议这样设:

只要出现一次 500 就告警
CPU 超过 60% 就告警
接口超过 500ms 就告警

这些阈值不是一定错,而是太容易脱离业务基线。比如有的后台报表接口 2 秒也能接受,有的登录接口 500ms 就已经偏慢。告警最好先看一段时间正常数据,再定阈值。

更实用的方式:

场景 告警建议
服务不可用 1-2 分钟连续健康检查失败
错误率升高 5 分钟内 5xx 超过阈值
响应变慢 P95 连续 10 分钟超过阈值
数据库异常 连接池耗尽或慢查询明显增多
磁盘风险 磁盘使用率超过 80%

6. 一次接口变慢怎么排查

假设用户反馈:

用户列表页面今天很慢

不要第一反应就改代码。按顺序看:

  1. 看监控:是不是只有 /users 慢,还是所有接口都慢。
  2. 看流量:请求量有没有突然变大。
  3. 看错误率:慢的同时有没有 500。
  4. 看日志:找慢请求的 request_id
  5. 看 SQL:有没有慢查询,分页是否失效。
  6. 看依赖:Redis、数据库、第三方服务是否异常。
  7. 看发布:最近有没有上线新版本。

常见结论:

现象 可能原因 下一步
只有一个列表接口慢 SQL、分页、N+1 查询 看慢 SQL 和 ORM 加载
所有接口都慢 CPU、数据库、网络 看机器和依赖
登录接口慢 密码 hash、数据库、限流 看 auth 日志
RAG 检索慢 向量库、embedding、top_k 太大 看检索耗时

7. 常见错误

错误 后果 修正
只打印 print() 线上难收集、难过滤 使用 logging
日志没有 request_id 多条日志串不起来 每次请求生成 request_id
只看平均响应时间 慢接口被平均值盖住 看 P95/P99
告警太敏感 大家疲劳,不再处理 设置持续时间和阈值
日志里打印密码/token 安全风险 敏感字段脱敏
没有慢查询记录 数据库问题难定位 开启慢查询日志或埋点

8. 检查清单

[ ] 每个请求有 request_id
[ ] 日志包含 method、path、status_code、duration_ms
[ ] 错误日志包含堆栈
[ ] 日志不打印密码、token、密钥
[ ] 有健康检查
[ ] 有 QPS、响应时间、错误率监控
[ ] 能看到数据库慢查询
[ ] 告警有阈值、持续时间、排查入口

9. 小结

名词 大白话
日志 系统日记
指标 系统仪表盘
告警 系统报警器
request_id 一次请求的小票号
P95 大部分用户真实感受到的速度
慢查询 数据库里拖慢接口的 SQL

上一篇建议:先看《FastAPI 项目配置、多环境和部署上线》,知道服务怎么上线。

下一篇建议:继续看《CI/CD、发布和回滚》,把上线流程变得可重复。

Checkpoint

读完后做题闯关

读完后做选择题检验理解,答错会显示解释。

0/1
先完成阅读

读完正文后点击“我已读完,进入练习”,题目会变成可答状态。

第 1 题

读完这一篇后,最适合怎么确认自己真的理解了?