Jaeger 中基于 MCP Skill 的 N+1 查询模式检测指南
Jaeger 中基于 MCP Skill 的 N1 查询模式检测指南【免费下载链接】jaegerCNCF Jaeger, a Distributed Tracing Platform项目地址: https://gitcode.com/GitHub_Trending/ja/jaeger分布式系统中N1 查询N1 Query是最隐蔽也最常见的性能杀手之一一次对外请求触发父操作父操作再串行或并发地发起大量几乎相同的下游调用典型如对数据库的逐条查询、对下游服务的逐个 RPC。在 Jaeger 的调用链视图里它的特征非常明显——一个父 Span 下挂着十几个乃至上百个同名的子 Span。本文基于 Jaeger 仓库内置的 MCP Skill detect-n-plus-one/SKILL.md完整讲解该 Skill 的触发条件、五步检测流程与判定阈值并结合仓库中search_traces、get_trace_topology、get_span_details三个 MCP 工具的源码实现说明这套流程为什么能区分真 N1与并行扇出等干扰场景。读完你可以直接在 Jaeger 的 MCP 端点或 AI 聊天侧车上复现这套诊断方法。N1 问题与 Jaeger Skill 机制的背景N1 检测能力属于 Jaeger 为 AI Agent 提供的trace 分析技能Skill体系。在该体系中Skill 是一份 Markdown 格式的剧本playbook由 Agent 在执行 trace 分析任务前读取它承载了纯粹的遥测工具无法承载的判断力哪两个看起来相似的 trace 其实是 N1哪个报错的 span 是根因而哪个只是无辜旁观者。具体机制可参见 mcptools 包 README 与 AUTHORING.md。Skill 通过read_skill工具被 Agent 获取入口是根索引 skills/SKILL.md采用**渐进式披露progressive disclosure**设计Agent 先读根索引根据每行链接旁的触发描述决定是否打开某个子 Skill从而控制上下文密度。detect-n-plus-one 与 error-root-cause 是随 Jaeger 二进制内置的两个示例 Skill。在进入检测流程前需要先确认 MCP 端点已开启。在配置中启用extensions.jaeger_query.ai.mcp空块即可extensions: jaeger_query: ai: mcp: {}端点运行在 query 端口的basePath/api/ai/mcp/上提供遥测工具与携带内置 Skill 的read_skill。运营方还可以通过ai.mcp.skills_dir挂载自定义 Skill 目录详见 mcptools/README.md。Skill 元数据与触发条件When this appliesdetect-n-plus-oneSkill 的 YAML frontmatter 定义了它的身份与工具边界--- name: detect-n-plus-one description: - Detect N1 query patterns in a trace, where one parent operation triggers many near-identical child spans (often database calls). Use when a trace is slow and shows repeated downstream calls, or when the user asks about N1, repeated queries, or chatty DB access. license: Apache-2.0 metadata: author: jaegertracing version: 1.0 allowed-tools: search_traces get_trace_topology get_span_details ---值得注意两点allowed-tools仅是文档性声明Jaeger 解析 Skill 时不读取任何 frontmatter 字段read_skill.go 原样返回文件内容它标记流程预期使用的工具并非沙箱也不阻止 Agent 调用其他工具description与根索引中的触发行保持一致保证目录描述与技能本体不会漂移。触发条件是 Skill 被读取的关键当一个父 Span 拥有大量同名、时长相近的子 Span典型为数据库查询或 RPC 调用时适用。按 AUTHORING.md 中的设计原则触发行必须在运行 Skill 之前就可判定——这里的两条来源都合法且廉价一条来自用户的原话用户询问 N1、重复查询或聊天式 DB 访问一条来自可廉价观察的事实trace 很慢且显示重复的下游调用。检测流程五步判定 N1Skill 的正文本体给出了一套五步检测流程下面结合 MCP 工具的源码逐一展开。第 1 步用 search_traces 定位候选 trace通过search_traces找到候选 trace。该工具返回不含完整 span 细节的 trace 摘要专为浏览和过滤大批量结果而优化实现见 search_traces.go。其输入参数定义于 types/search_traces.go包括参数类型默认值说明start_time_min/start_time_maxstring-1h/now时间区间支持 RFC3339 或相对时间如-30m、-5sservice_namestring无按服务名过滤省略则搜索全部服务部分存储后端不支持并会拒绝span_namestring无按 span 名过滤attributesobject无键值对匹配 span/resource 属性with_errorsboolfalse为 true 时只返回含错误 span 的 traceduration_min/duration_maxstring无时长过滤如2s、100mssearch_depthint10最大搜索深度上限由服务端MaxSearchResults配置控制从源码可见其内部校验逻辑相对时间解析支持now、-duration前缀及 RFC3339start_time_max必须晚于start_time_minduration_max必须大于duration_minwith_errorstrue时会在属性过滤中注入errortrue。返回的每个TraceSummary包含trace_id、根服务与根 span 名、起止时间、duration_us、span_count、service_count、服务列表及has_errors标记足够 Agent 快速筛选出慢且含重复下游调用的候选。第 2 步用 get_trace_topology 拉取 span 树并按父分组对候选 trace 调用get_trace_topology获取结构树。该工具刻意不返回属性和日志以保持响应紧凑只暴露父子关系、时序与错误位置实现见 get_trace_topology.go。其核心数据结构是rawSpan每个 span 只保留spanID、parentID、service、spanName、startTime、durationUs、status 与用于排序的startNano。服务端处理要点通过jptrace.AggregateTracesWithLimit保证完整 trace 视图的同时将服务端内存限制在maxSpanDetailsPerRequest个 span 以内防止超大 trace 造成无界开销用buildFlatTopology做 DFS 深度优先遍历输出扁平列表每个 span 的Path字段编码为从根到自身的斜杠分隔的 span ID 链孤儿 span 会在路径前补上缺失的父 ID方便定位挂接点支持Depth参数截断深度超深子节点以TruncatedChildren计数标记而不展开根节点与兄弟节点均按开始时间升序稳定排序保证输出确定性。拿到扁平拓扑后Skill 要求在每个父 Span 下按 operation name 对子 Span 分组——这正是检测 N1 的原始素材。第 3 步按阈值标记可疑分组对每个分组应用两个判定条件数量条件同组近似相同的兄弟 Span 数量超过10 个标记为潜在 N1 模式时长条件检查子 Span 时长是否相似判定标准为在中位数的 2 倍以内within 2x of the median。从 AUTHORING.md 可知这条判定规则经历过一次重要修正最初的规则只写了时长相似中位数 2 倍以内但用真实捕获的 trace 对照测试后发现——并行扇出在该标准下得分 82%而真实 N1 仅得分 77%真实 N1 中的一次重试使时长更不均匀导致负样本反而更像 N1且规则从未说明需要多少兄弟节点符合。修复方案改为同时比较兄弟时长之和与从最早开始到最晚结束的 elapsed 窗口两者大致相等则读作串行执行。这正是 Gotchas 部分第 1 条背后的量化依据。第 4 步用 get_span_details 确认重复兄弟对可疑的重复兄弟 Span 调用get_span_details实现见 handlers 目录确认两点它们是否指向同一个下游服务是否携带相似的属性如相同的 SQL 语句模板、相同的下游端点。这一步是确认而非猜疑只有目标一致、属性近似的兄弟组才构成同一类重复调用才能与第 2 步的分组证据互相印证。第 5 步输出报告最终报告必须携带以下证据字段缺一不可父 Span服务名与 operation name重复的子操作operation name数量重复兄弟的计数总墙钟时间消耗这些重复调用合计占用的时间执行方式子 Span 是串行还是并行执行。按 AUTHORING.md 的设计要求Skill 的收尾步骤必须说明报告什么、携带什么证据这正是防止 Agent 给出自信却无依据的摘要的关键。Gotchas容易误判的两种场景Skill 的 Gotchas 部分收录了明显解读会出错的两种情况它们通常是 Skill 存在价值的核心并行扇出 ≠ N1并行扇出parallel fan-out在拓扑上同样表现为一个父 Span 带大量同名子 Span但它是有意的架构设计如批量并行处理、map-reduce 风格。区分要点是检查子 Span 在时间上是否重叠真 N1 通常是串行执行前一个查询等待返回后才有下一个子 Span 首尾相接、几乎不重叠而并行扇出的子 Span 开始时间集中、时间窗口大面积重叠。判定时可以参考第 3 步的量化手段——比较兄弟时长之和与 elapsed 窗口的关系大致相等判定为串行反之倾向并行。批量操作共享 operation name 但负载不同批量操作batch可能共享同一个 operation name但每次携带的 payload 不同。此时必须检查 span 属性加以区分如果各兄弟 Span 的属性如请求体、参数、被操作的对象 ID差异明显它们只是共享名字的独立批量请求而非对同一资源的重复低效调用。这正是第 4 步要求携带相似属性才能确认的原因。Skill 如何被读取与安全边界理解了检测流程再看 Skill 的读取链路会更有价值。read_skill处理器read_skill.go按路径前缀路由custom/前缀指向运营方配置的skills_dir未配置则一律返回 not-exist其余路径从内置skills_fs读取。两个硬性限制值得注意路径包含性目录以os.OpenRoot打开..穿越与指向skills_dir之外的符号链接由操作系统直接拒绝而非依赖可被绕过的路径检查文件大小served 文件上限 512 KiB超出部分截断并追加file content truncated after 524288 bytes标记。此外Skill 是静态文本Jaeger永不执行它们读取并执行的是 Agent 自己。skills_dir属于可信配置面——能写入该目录的人就能在不改动二进制与配置的情况下引导 Agent 行为因此应将其归属 root 或 Jaeger 服务账户并像审核配置变更一样审核其中的改动详见 mcptools/README.md。验证与最佳实践验证 Skill 是否生效可用 MCP 客户端直接请求入口点read_skill(pathdetect-n-plus-one/SKILL.md)返回 Skill 文本即表示内置 Skill 可访问如需验证自定义目录则请求read_skill(pathcustom/SKILL.md)返回cannot read custom/SKILL.md说明要么未配置skills_dir要么文件不存在于该名称下。从 AUTHORING.md 总结的编写与测试经验同样适用于理解这套 Skill 的质量标准构造对抗性测试样本能令任何合理流程都成功的 trace 证明不了什么应选择朴素答案与正确答案不同的样本机械地推导预期答案预期标签应来自可测量的时序或刻意注入的故障而不是事后可被悄悄修正的判断每个步骤都要命名度量并说明每种结果的处置包括负样本情形廉价的反证检查排在前昂贵的逐 span 查询排在后单个 Skill 建议控制在约 500 行约 5,000 token以内一旦覆盖了两种读者会分别到达的情境就应拆分。小结detect-n-plus-oneSkill 是 Jaeger MCP 技能体系中用程序化步骤承载专家判断的典型范例以慢 trace 重复下游调用为廉价触发点用search_traces收敛候选、get_trace_topology按父分组并做数量10与时长中位数 2 倍内、串行/并行窗口对比双重判定、再用get_span_details核对下游服务与属性完成确认最后输出带完整证据的报告。这套流程不仅有清晰阈值还通过真实 trace 样本验证并修正过判定标准直接阅读仓库内的 SKILL.md、AUTHORING.md 与对应 handler 源码即可完整复现并延伸这套诊断能力。【免费下载链接】jaegerCNCF Jaeger, a Distributed Tracing Platform项目地址: https://gitcode.com/GitHub_Trending/ja/jaeger创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考