通过仅发送关键数据降低 FastAPI 中 Sentry APM 成本

发布: (2026年1月8日 GMT+8 14:41)
5 分钟阅读
原文: Dev.to

抱歉,我需要您提供要翻译的具体文本内容(文章正文),才能为您完成翻译。请把文章的文字粘贴在这里,我会保持原有的格式和代码块不变,只翻译正文部分。

默认 APM 的真正问题

默认情况下,Sentry APM 非常慷慨:

  • 每个请求都会成为一个事务
  • 即使是子秒级的成功调用也会被记录
  • 文档和 schema 端点也会被追踪

对于高流量 API,这很快会变成:

  • 大量事务
  • 更快的配额耗尽
  • 为噪音付费,而不是洞察

实际上,我只需要关注:

  • 失败的请求(5xx)
  • 运行缓慢的请求
  • 任何异常或有风险的情况

其他的都只是背景噪音。

成本节约策略

始终发送至 Sentry

  • 任何返回 5xx 的请求
  • 任何耗时超过 5 秒 的请求

从 Sentry 中剔除

  • 快速的 GET / POST / PUT 请求
  • 3 秒 内成功完成的请求
  • /docs/openapi.json 端点

这使 Sentry 专注于问题,而不是流量量。

Source:

为什么需要两个中间件

SentryAsgiMiddleware – 启用 APM

SentryAsgiMiddleware 实际上会:

  • 启动并结束 Sentry 事务
  • 挂钩到 ASGI 请求生命周期
  • 将性能数据发送到 Sentry

如果没有这个中间件:

  • 不会创建事务
  • before_send_transaction 永远不会被调用
  • APM 根本无法工作

简而言之: 没有 SentryAsgiMiddleware = 没有 APM

TimingMiddleware – 添加智能

第二个中间件是自定义的。它测量每个请求的真实执行时间,并将其附加到 Sentry scope。

class TimingMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        start_time = time.time()
        response = await call_next(request)
        duration = time.time() - start_time

        with sentry_sdk.configure_scope() as scope:
            scope.set_extra("duration", duration)

        return response

需要它的原因:

  • 执行时间是判断请求是否“重要”的依据
  • Sentry 内部的计时信息不易用于过滤
  • 没有它,成本控制逻辑只能靠猜测

可以这样理解:

  • SentryAsgiMiddleware 是管道
  • TimingMiddleware 是大脑

在发送事务之前过滤事务

Sentry 提供了一个名为 before_send_transaction 的钩子。它在事务发送到 Sentry 之前运行,允许你丢弃该事务。

def before_send_transaction(event, hint):
    transaction_name = event.get("transaction", "")
    request_method = event.get("request", {}).get("method", "")
    status_code = event.get("contexts", {}).get("response", {}).get("status_code", 0)

    duration = event.get("extra", {}).get("duration")

    # Ignore docs and schema
    if "/docs" in transaction_name or "/openapi.json" in transaction_name:
        return None

    # Always send server errors
    if status_code >= 500:
        return event

    # Drop fast successful requests
    if (
        request_method in ["GET", "POST", "PUT"]
        and 200 <= status_code < 400
        and duration
        and duration < 3
    ):
        return None

    return event
  • 返回 event → 事务将被发送
  • 返回 None → 事务将被丢弃

简单、可预测,且完全由你掌控。

初始化 Sentry 并自定义过滤

sentry_sdk.init(
    dsn="SENTRY_DSN",
    send_default_pii=True,
    traces_sample_rate=1.0,
    before_send_transaction=before_send_transaction,
)

而不是依赖随机抽样,这种方法基于真实行为提供确定性的过滤。

变更内容

成本降低

交易量急剧下降,Sentry 使用量立即放慢。

更简洁的仪表盘

仅显示慢速或失败的请求,使调试更容易。

更好的信号

Sentry 中的每一次交易现在都意味着 “值得关注”。

当这种方法有意义时

  • 您的 API 流量很大
  • 大多数请求成功且快速
  • 您更关注问题而非原始指标

如果您希望每个请求永远被追踪,这种方法并不适合。如果您想在不浪费金钱的情况下获得有用的可观测性,这正是合适的选择。

最终思考

APM 应该帮助你发现问题,而不是在计费仪表板中制造新问题。

通过组合:

  • SentryAsgiMiddleware
  • 一个简单的计时中间件
  • before_send_transaction

你将 Sentry 从 “collect everything” 转变为 “collect what actually matters.” 这一小小的改变在真实的生产系统中会产生巨大的差异。

Back to Blog

相关文章

阅读更多 »