SaaS 性能监控与产品分析:2026 全面指南

2026 年 SaaS 性能监控与产品分析统一指南——五层遥测、SLI/SLO、成本经济模型,以及个人开发者的可观测性技术栈实践。

Huifer
Huifer
July 12, 202612 min read
其他语言:Deutsch · English

本文由 Huifer 撰写,TanStack Ship 的独立开发者与维护者。 我在 12 个以上运行于 Cloudflare Workers 的 TanStack Ship SaaS 应用中同时运行性能监控与产品分析——这些应用为数万月活用户提供服务,由我构建、出现问题时也会先通知我。分工如下:性能侧是边缘指标、结构化日志和 Tail Worker 追踪;产品分析侧是自托管 PostHog;两者通过从浏览器到 Worker 再到数据库的共享请求 ID 连接。本文中每个阈值、查询和告警都是我实际交付的。提前声明对 TanStack Ship 的偏向——这是我的付费产品。

经验证的信息来源: Cloudflare Workers Analytics Engine · Cloudflare Workers Observability · Web Vitals · OpenTelemetry · PostHog open-source product analytics · Google SRE Workbook — SLO chapter

最近更新:2026-07-12 · 更新日志


TL;DR: 性能监控与产品分析并非同一学科,但孤立地运行时失败方式相同——性能告诉你某个指标动了,用户却做了什么它不知道;分析告诉你用户做了什么,系统是否承载了他们的行为它不知道。我在 2026 年 Cloudflare Workers 上运行的统一技术栈包含五层性能指标加一层产品分析,通过请求 ID 关联,包装在 SLI 和 SLO 中,仅在用户可见的性能下降时触发告警。本文涵盖五层遥测栈、产品分析层、SLI/SLO 计算、三种应用规模的成本经济模型、仪表板,以及每周复盘机制。


为什么监控与分析需要放在同一个语境下

大多数 SaaS 团队将监控与分析作为两个独立的技术栈运行——一个用 Datadog,另一个用 Mixpanel——绘制两张仪表板,从不关联数据。结果是一幅碎片化的图景:每个问题你只能回答一半。

单独依赖监控的盲区

性能技术栈用指标、日志和追踪来回答「系统健康吗?」这个问题。它能检测到 /api/checkout 的延迟发生了回归、部署后 5xx 错误率飙升,或者某个数据库查询现在扫描的行数从 40 变成了 40,000。但它无法告诉你这次峰值是影响了一个用户还是一万个用户,是落在了转化路径上还是一个无人访问的管理后台,以及是否是新功能触发了这次回归。

我为此付出了昂贵的代价。2026 年第一季度,一次 TanStack Ship 计费模块 部署将 p95 结账延迟从 320ms 推高到了 780ms。告警触发了,回滚执行了,我以为一切良好——直到分析仪表板显示在回归上线的 4 个小时内,转化率下降了 11%。监控告诉我「出了问题」;但它无法告诉我「什么正处于风险之中」。

单独依赖分析的盲区

产品分析回答「用户做了什么?」——注册、激活、漏斗下降、留存、功能采用。它告诉你试用转付费转化上周下降了 4 个百分点。但它无法告诉你「为什么」——是升级流程中的 bug、一次跨越了可用性阈值的减速,还是上游 OAuth 服务中断。

我曾辅导过的一个 SaaS 团队靠纯产品分析运行了两个月。他们的转化率下降源于一次缓慢的 OAuth 握手过程,在首次登录时增加了 4 秒延迟。他们在 OAuth 路径上没有任何追踪数据,是通过阅读一条支持工单的相关日志才找到根因的。

「统一」的实际含义

统一并不意味着单一供应商。它意味着一个共享标识符——一个由浏览器发送、Worker 记录、分析事件携带、数据库查询附着的请求 ID。一旦同一个 ID 同时出现在两个仪表板中,你就能回答单靠任何一方都无法回答的问题。

实践中,就是在客户端生成一个 UUID,传播到每个服务端事件,写入 Analytics Engine 行、附加到 PostHog 事件、并标记到 D1 查询。以该 ID 关联后,两个技术栈就变成了一个。

我运行的五层性能技术栈

性能遥测分为五层。每一层都有其职责;没有任何一层可以替代另一层。

第一层:Workers Analytics Engine 上的边缘指标

聚合指标存储在 Workers Analytics Engine 上——一个面向高基数边缘负载的时间序列数据库:写入密集型、支持 SQL 查询、成本低。

sql
-- 过去 6 小时内每条路由的 p95 延迟
SELECT
  blob1 AS route,
  int2 AS status_class,
  quantileCont(0.95)(double4) AS p95_ms
FROM response_metrics
WHERE timestamp > NOW() - INTERVAL '6' HOUR
GROUP BY route, status_class
ORDER BY p95_ms DESC
LIMIT 25;

每个 Worker 在每次响应时写入一行,包含路由、状态类、耗时和维度列(部署 ID、地域、请求 ID)。每个应用一个仪表板,每 5 分钟拉取一次此查询。同样的数据为驱动告警的 SLI 计算提供输入。

第二层:Workers Logs 和 Tail Workers 中的结构化日志

指标告诉你一个数字动了;日志告诉你哪些请求中包含了这个数字。Workers Logs 捕获控制台输出和异常追踪,内置请求关联。我记录结构化 JSON,这样可以用 jq 搜索并导入事件复盘。

Tail Worker 保存每个请求的详细信息——已脱敏 PII 的请求日志、不含 Cookie 的请求头、正文形状而非正文值的请求体,以及将所有信息串联起来的请求 ID。默认采样率为 1/10;调试任何部署时提升到 100%。

第三层:通过 Tail Workers 和 OpenTelemetry 的分布式追踪

追踪回答「哪个数据库查询、在哪个下游调用中、在哪个部署上、导致了这次回归」。OpenTelemetry 模式在 Workers 上可用,但有一个注意事项——没有进程内代理,所以我从 Tail Worker 导出 OTLP。

ts
// tail-worker.ts — 为每个采样请求发出一个 OTLP span
export default async function (events: TraceItem[], env: Env) {
  const spans = events.map((e) => ({
    traceId: e.requestId,
    name: `${e.event.request.method} ${e.event.request.url}`,
    startTimeUnixNano: e.event.cp,
    endTimeUnixNano: e.event.cp + (e.event.wallTimeMs * 1_000_000),
    attributes: {
      'http.method': e.event.request.method,
      'http.route': e.event.scriptName,
      'http.status_code': e.event.response?.status,
      'deploy.id': env.DEPLOY_ID,
    },
  }));
  await fetch(env.OTLP_ENDPOINT, {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify({ resourceSpans: [{ spans }] }),
  });
}

我尚未在 5k spans/s 以上的持续负载下做过基准测试——在我操作的规模下这从未成为瓶颈。如果你超过了这个阈值,切换到采样 tail worker。

第四层:基于 web-vitals + beacon 的真实用户监控

服务端指标告诉你边缘看到了什么。RUM 告诉你用户设备实际经历了什么。两者会产生分歧——你的边缘可以在 80ms 内返回 200,但用户看到的是 6 秒的 LCP,因为第三方脚本阻塞了主线程。我的 RUM 指南 覆盖了完整实现;简言之就是浏览器中的 web-vitals,向 Worker 端点发送 sendBeacon,同一个请求 ID 流入 Analytics Engine 并标记 source=rum。

采样率是一个陷阱。100% 会烧光 CPU 和配额;1% 会失去对低流量租户的可见性。我在全球范围内采样 10%,在错误响应时采样 100%,在任何活跃事件期间采样 100%。

第五层:基于定时触发 Worker 的合成检查

RUM 只在真实用户访问路由时触发。合成检查则在无人关注时也会触发。定时触发的 Worker 每分钟从三个地域访问最关键的路径——登录、注册、升级流程、定价页。延迟回归首先在这里显现。

2025 年一次 D1 写入竞争事件中,我深刻认识到合成检查的价值:合成检查器比第一个客户影响早 90 秒通知了我。

让性能变得有意义的产品分析层

性能告诉你系统动了什么。产品分析告诉你哪个用户做了哪个动作。两者一起才能回答那个付账单的问题。

控制成本的事件收集

我在一台小型 VM 上自托管 PostHog。它捕获重要的事件——注册、激活、升级、流失、功能使用——并通过请求 ID 关联到性能数据。成本与月活跃用户数挂钩,而非事件数——这是 SaaS 的正确成本形态,每个用户产生数十个事件。

一个常见错误:全量埋点。我将客户端事件控制在约 12 个命名事件。原则是:如果一个事件不会改变我本会做出的决策,我就不收集它。

漏斗、留存和功能使用

三个分析视图在每个 SaaS 仪表板上都能发挥价值:

  1. 激活漏斗——从落地页到用户首次感知产品价值的 4 到 6 个步骤。下降 5% 即为回归。
  2. 队列留存——每个注册周的用户在第 N 周仍然活跃的百分比。这个曲线形状比任何单一指标都更能说明你的产品。
  3. 功能使用热力图——付费用户中接触过每个功能的比例。低于 5% 是移除候选;高于 40% 是加投候选。

将产品事件关联到性能追踪

这是统一技术栈得名的地方。每个 PostHog 事件都携带 request_id 属性。每个 Analytics Engine 行也携带同一个 ID。查找导致付费客户流失的慢速结账路径:

ts
// 查找取消订阅用户的性能追踪
const slowCheckout = await analytics.query(`
  SELECT * FROM response_metrics
  WHERE timestamp > NOW() - INTERVAL '7' DAY
    AND blob1 = '/api/checkout'
    AND double4 > 500
    AND blob3 IN (
      SELECT distinct_id FROM posthog_events
      WHERE event = 'subscription_cancelled'
        AND timestamp > NOW() - INTERVAL '7' DAY
    )
  LIMIT 100;
`);

这个查询就是「上周结账变慢了」与「结账在取消订阅的队列中变慢了,这里是可以查看的请求 ID」的差距。它是单靠任何一方都无法回答的问题。

真正通知对的人的 SLI、SLO 和错误预算

没有 SLI 和 SLO,告警会对每个波动的指标都触发。有了它们,告警只会在用户感受到你承诺不会施加的痛苦时触发。

选择用户能感知的 SLI

SLI 是一个比率:好的事件数除以有效事件数。我追踪的四个 SLI:

  1. 可用性——2xx 响应数除以所有响应数,不含重定向。
  2. 延迟——300ms 以内的响应数除以所有响应数,按 p95 计算。
  3. 正确性——成功写入数除以所有写入尝试数。
  4. 新鲜度——成功的后台任务运行数除以计划运行数。

原则是「用户能感受到什么」。队列深度是信号;除非用户能感知到它,否则它不是 SLI。

经得起实践检验的 SLO 目标

一个达不到的目标是表演。一个太容易达到的目标不是契约。我运行的目标:

  • 可用性:滚动 28 天窗口内 99.9%(每月约 40 分钟预算)
  • 延迟:p95 下 95% 的请求在 300ms 以内
  • 正确性:写入操作 99.99%
  • 新鲜度:后台任务 99%

我按季度审视这些目标。消耗预算低于 50% 的应用是收紧的候选;消耗超过 80% 的是真正可靠性投入的候选。

告警路由与燃烧率告警

SLO 的意义在于错误预算——你在一个窗口内允许自己的糟糕程度。燃烧率告警在预算消耗速度不可持续时触发。我运行两个:

  1. 快速燃烧——1 小时内消耗 2% 预算。直接电话告警。
  2. 慢速燃烧——24 小时内消耗 5% 预算。Slack 通知,不电话。

在我运行的每个应用上,燃烧率告警已取代阈值告警。调优大约花了一个月,每季度的告警电话减少了约 4 倍。

成本经济模型:三种 SaaS 规模,两种技术栈

我被问到最多的问题是「这个技术栈实际成本是多少?」取决于规模,但成本形状是可预测的。

小型应用——MAU 低于 5 万

Cloudflare 原生技术栈基本上免费。Workers Analytics Engine 在付费 Workers 计划中每天包含 10 万个事件;$5/月的 VM 上自托管 PostHog 处理分析。同等规模下第三方技术栈——Datadog 加 Mixpanel——约 $80-200/月。免费技术栈的吸引力是明显的。

中型应用——MAU 5 万到 10 万

免费技术栈开始出现摩擦。Analytics Engine 写入量随规模线性增长;在 10 万 MAU 时很可能触及包含配额的限制,需要付费附加包或激进采样。总月运行成本:$30-200。

同规模第三方技术栈为 $400-1,500/月。Cloudflare 原生技术栈的经济账很扎实——但运营上的取舍是真实的。我有一款应用在这个量级使用第三方技术栈,因为自管理追踪的在岗负担不值得那些节省。

较大型应用——MAU 高于 10 万

到这个规模两种技术栈成本趋同,第三方技术栈通常在功能上胜出。Datadog APM、Honeycomb 的 BubbleUp、New Relic 的错误追踪是成熟产品,有多年投入。总月运行成本:$200-1,500(Cloudflare 原生)对比 $1,500-6,000(托管技术栈)。

托管可观测性技术栈胜出的场景

三个经验法则:

  1. 如果你的工程团队超过两人,Datadog 或 Honeycomb 的协作功能通常物有所值。
  2. 如果你的追踪量超过约 5,000 spans/s 持续负载,托管技术栈的索引管道比我自建的任何方案都更可靠。
  3. 如果你在多个云服务商上运营,第三方技术栈是获取统一视图的唯一途径。

对于在 Cloudflare Workers 上运行 SaaS 的独立开发者应用——这正是 TanStack Ship 的设计目标——Cloudflare 原生技术栈是更好的默认选择。

仪表板、告警路由和每周复盘

不看的遥测数据就是浪费的遥测数据。

三个仪表板,不是三十个

我运行的每个 TanStack Ship 应用有三个仪表板:

  1. 生产健康——p95 延迟、错误率、请求量、部署标记叠加。一屏可扫。
  2. 用户漏斗——注册 → 激活 → 升级 → 留存。周视图。
  3. SLO 状态——每个 SLI 当前 28 天错误预算剩余量,用绿/黄/红颜色编码。

其他一切都是下钻,不是顶级仪表板。如果一个回归没有出现在三个仪表板中的某一个上,它就不值得一个告警。

告警严重级别阶梯

四个级别:

严重级别路由示例
P0电话告警快速燃烧 SLO 告警、完全中断
P1Slack + 电话持续错误率超标、部署回归
P2Slack慢速燃烧 SLO 告警、单一路由延迟回归
P3邮件/摘要容量警告、证书过期

我看到最常见的错误是 P1 过多。如果一切都是 P1,就没有 P1 了。阶梯迫使你回答一个问题「凌晨 3 点我真的会采取行动吗?」——如果答案是「等到早上再说」,那就不是 P1。

周一早晨复盘机制

每周一上午 9 点,我花 30 分钟回顾:

  • 上周的 SLO 燃烧率
  • 按用户影响排名前三的延迟回归
  • 排名前三的转化漏斗变化
  • 任何 P0/P1 事件及其事后分析状态

这就是整个机制。两年来我没有漏掉任何客户可见的回归——每周复盘捕获了告警遗漏的问题。

技术栈作为一个整体系统

监控与分析在孤立地运行时以同样的方式失败:每个只能回答每个问题的一半。通过请求 ID 关联,并以 SLI/SLO 作为契约,它们就变成了一个整体——只在用户可见的性能下降时告警,将遥测数据与业务成果关联起来,成本上是独立开发者的时间但不是托管平台预算。

我在 2026 年运行的技术栈并不另类。它是被凌晨 3 点告警太多次之后的无聊结论:五层性能、一层分析、一个共享标识符、SLO、三个仪表板,加一个周一早晨复盘。如果你在 Cloudflare Workers 上发布 SaaS 而没有运行接近这个的系统,TanStack Ship 样板 已经预置了遥测层——所以你从我不得不自己摸索的地方开始。


下一步: 阅读可观测性深度解析了解三支柱实现细节,阅读 RUM 指南了解客户端埋点,阅读分析技术栈设置了解我运行的 PostHog 配置。在决定哪个样板为你承载遥测之前,将 TanStack Ship 的监控默认值与 Shipfast 和 Makerkit 进行对比。