mcpField
D
diagnosing-endpoint-performance

diagnosing-endpoint-performance

github.com/posthog数据与数据库96179 次安装今天更新
代码仓库

关于 diagnosing-endpoint-performance

用于诊断 PostHog 中特定的缓慢、高成本或不稳定端点,并提出具体建议。它指导检查缓存、物化条件、查询改写和版本历史。

主要功能

  1. 01检查端点配置与版本
  2. 02评估缓存 TTL 和物化条件
  3. 03查看调用频率与查询成本
  4. 04分析查询改写及回滚选项

适用场景

  1. 01排查缓慢或超时的端点
  2. 02评估是否应物化端点
  3. 03根据查询版本追踪回归

MCP 相关

该技能使用 MCP 提供的端点、物化、版本、执行和 SQL 工具进行调查与诊断。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/posthog/ai-plugin --skill diagnosing-endpoint-performance

安装后在 Claude Code 中输入/diagnosing-endpoint-performance确认已加载。

详细介绍

诊断端点性能

此技能将分析某个具体的端点,该端点可能速度慢、成本高或不可靠,并给出明确的建议。它是 auditing-endpoints(用于发现候选端点)的深度分析对应技能。

何时使用此技能

  • “这个端点速度慢/超时了”
  • “为什么我的端点触及了成本上限?”
  • “我应该物化 X 吗?”
  • 某个端点在 auditing-endpoints 中被发现,其物化失败或调用成本高
  • 用户心中已有特定端点,并希望获得建议

如果问题涉及整个项目(“我应该清理哪些内容?”),请先使用 auditing-endpoints。

可用工具

工具用途
endpoint-get完整的端点配置:查询、当前版本、data_freshness_seconds、物化状态
endpoint-versions每个版本的历史记录(查询及物化状态);以及当前版本
endpoint-materialization-status是否符合物化条件、当前状态、上次运行时间、上次错误
endpoints-materialization-preview物化后的查询会是什么样,以及不符合条件时的拒绝原因
endpoints-last-execution-times上次调用时间(用于检查端点是否仍在使用)
execute-sql查询 query_log,查看端点级调用频率以及每次调用的时长/字节数

决策树

决定给出什么建议时,请按以下顺序逐项检查——最先适用的选项就是成本最低的修复方式。

第 1 步——是否已缓存?

获取端点并查看 data_freshness_seconds(它既设置缓存 TTL,也设置物化后的刷新频率)。如果用户的流量在此时间窗口内重复使用相同参数调用端点,那么首次调用之后的每次调用都会命中缓存,实际无需付费。

  • TTL 为默认值(24h / 86400s),且数据无需比这更新鲜 → 无需更改。
  • TTL 为下限 900s(15 min),且用户每分钟调用端点多次 → 提高 TTL。这几乎总是成本最低的首选操作。(data_freshness_seconds 是一个枚举值:900、1800、3600、21600、43200、86400、604800——最短间隔为 15 分钟。)
  • TTL 已处于下限,因为数据必须保持最新(例如,实时仪表盘)→ 缓存无济于事,转到第 2 步。

变量的取值方式在这里很重要:如果每次调用都传入不同的 user_id 或 date_from 值,缓存会有许多不同的键,提高 TTL 的帮助就较小。如果几乎每次调用都使用少数几种相同的参数组合,缓存就会很有用。

步骤 2 — 是否应该进行物化?

物化会预先计算查询,并将结果保存为定期刷新的视图。读取速度会接近即时响应,但代价是数据会因刷新间隔而过时,还需要为物化本身消耗存储和计算资源。

调用 endpoints-materialization-preview。响应会告诉你:

  • 符合条件且转换逻辑简洁 → 强烈建议物化。尤其是筛选形态可预测的端点(变量、细分维度)。
  • 不符合条件,并附有拒绝原因 → 无法物化。原因通常会提示下一步该怎么做(见步骤 3 — 重写)。
  • 符合条件,但转换逻辑复杂(范围对很多、需要复杂地重新推导聚合结果)→ 物化可以正常运行,但可能节省不了多少资源。在启用前值得先说明这一点。

启用物化后,调用方必须传入所有已物化变量——不带这些变量的调用会被拒绝(安全性:防止返回未筛选的数据)。建议启用时,同时注明哪些变量会成为必填项。

步骤 3 — 查询是否需要重写?

对于不符合物化条件的 SQL 端点,endpoints-materialization-preview 返回的拒绝原因是首要依据。该工具始终会解析成功。查看原因,并与以下要点匹配——这些要点概括了常见情况,并未涵盖服务端执行的所有检查;如果两者不一致,应以原始原因为准。手动提出重写方案:

  • 因群组细分 / 对比模式被拒绝 → 常规属性细分可以正常物化;只有群组细分会被阻止。将群组细分改为属性细分。趋势端点支持物化对比模式;其他查询类型则应移除对比模式(改为将对比时间窗口作为变量)。
  • JOIN 与变量组合使用 → 顶层 JOIN 加变量筛选会被拒绝物化,因为应用变量会改变连接后的行基数,并悄然产生错误结果(例如,LEFT JOIN 中不匹配的行会丢失变量列)。调整结构,让变量只筛选单个表——将筛选条件推入随后再进行连接的子查询 / CTE,而不是跨连接筛选。这是最常见的“看起来没问题,却无法物化”的陷阱。
  • “缺少变量” / 无界扫描 → 查询在没有筛选条件的情况下读取了过多数据。建议添加必填的时间窗口变量(例如 date_from、lookback_days)。
  • HogQL 使用 * / 非确定性函数 → 缩小所选列的范围,并尽可能用变量替换 now() / today()。
  • 没有要点匹配 → 上面的列表并不完整;实时检查会拒绝更多形式,包括 OR 中的变量、与另一个变量比较的变量、HAVING 子句中的变量、不受支持的运算符,以及无法物化的查询类型。将拒绝原因原样告知用户,并直接据此分析,而不要强行套用最接近的要点。有些原因根本没有等效的重写方式——例如 OR {variables.x} = 'all' 这种可选变量写法——应明确说明这一点,而不是改变查询的行为。

检查 endpoint-versions,确认查询近期是否有变更。回归问题往往源于某个特定提交,回退到该版本通常比重写更快。

第 4 步——实际调用的是慢版本吗?

默认只运行最新版本;只有调用方固定 ?version=N 时才会运行旧版本。因此,通常需要调整的是当前版本——除非问题出在某个固定使用的旧版本上。调用 endpoint-versions 并查看每个版本的 last_executed_at,以了解最近调用过哪些版本;如果某个物化版本的 last_executed_at 为 null 或已过时很久,那么与其调整,不如考虑取消物化或删除(请先确认——该信号只统计 API 密钥调用,可能较为稀疏)。

如需了解端点级调用频率和单次调用成本,请使用 execute-sql 查询 query_log——其中包含 query_duration_ms、read_rows 和 read_bytes,便于确认该端点调用的实际开销:

SELECT count() AS calls, max(query_start_time) AS last_called, avg(query_duration_ms) AS avg_ms
FROM query_log
WHERE name = '<endpoint_name>' AND endpoint LIKE '%/endpoints/%' AND is_personal_api_key_request

工作流

  1. 按名称识别端点。如果用户提供了 URL,请从 /api/projects/{team_id}/endpoints/{name}/run 中解析名称。
  2. 使用 endpoint-get 获取完整配置。注意:data_freshness_seconds、is_materialized、当前版本和查询类型。
  3. 使用 endpoint-materialization-status 查看物化状态(是否失败?是否符合条件?)。
  4. 使用 endpoint-versions 查看查询历史以及当前版本(除非调用方固定 ?version=N,否则调用方会使用该版本)。
  5. 如果用户提供了具体问题(“超时”“内存限制”“非常慢”),请按上述决策树逐步排查。否则,请说明这四项检查点,并询问用户符合哪一种情况。
  6. 最后给出明确建议——提高 TTL、物化、重写或回滚,并在执行前确认。

交互示例

User: "monthly_active_users is timing out for some callers"

Agent steps:
- endpoint-get monthly_active_users → HogQL endpoint, data_freshness_seconds=900,
  is_materialized=false, current version v4
- endpoint-materialization-status monthly_active_users → not materialised; eligible: true
- endpoint-versions monthly_active_users
  → v4 is current; v1–v3 are prior query revisions (callers hit v4 unless pinned)
- endpoints-materialization-preview → eligible, clean transform with one range pair

- "Three things stand out:
   1. Cache TTL is 900 seconds (the 15-min floor), but the data is
      aggregating a month — that aggressive a refresh probably isn't
      necessary. Bumping to 1 hour (3600s) would dramatically reduce
      ClickHouse load.
   2. It's eligible for materialisation with a clean transform. If
      callers can tolerate 5-15 minute staleness, materialisation
      would make reads near-instant.
   3. v4 is the current version, so callers hit it by default — the
      tuning target is clear.

   Quickest win: bump TTL to 3600s. Bigger win: materialise.

   Which trade-off matches your needs? If you need real-time freshness,
   neither helps and we'd need to rewrite the query — likely narrowing
   the aggregation window."

重要说明

  • 缓存几乎总是首选解决方案。 它无需成本、可立即撤销,也不会改变数据语义。如果提高 TTL 就能解决问题,请不要急着选择物化。
  • 物化存在隐性成本。 包括物化视图的存储、刷新计算,以及调用方必须传入所有变量这一要求。
  • 不要擅自重写查询。 修改查询会创建新版本,并可能导致调用方无法正常工作!!!请先说明建议的修改并获得同意,再执行。
  • 有三种使用情况信号。 endpoint-get 的 last_executed_at 表示端点级的最近调用时间;endpoint-versions 提供各版本自己的 last_executed_at;query_log(通过 execute-sql 查询)提供端点级调用频率和单次调用成本。这些信号都只统计个人 API 密钥调用,而且各版本的最近调用记录可能较为稀疏——在认定某个版本已停用之前,请先向用户确认。
  • “合适的”解决方案取决于 SLA,而非查询本身。 在建议物化之前,务必询问用户可接受的数据陈旧程度。对于实时仪表板,即使成本很低,存在 15 分钟延迟的物化视图也不合适。
  • 告知 PostHog 缺少什么。 如果诊断遇到产品限制(资格规则、TTL 枚举值、必需变量),请通过 agent-feedback 提醒团队。

评论

支持 Markdown