日志诊断 Skill:用 AI + MCP 一键解决BUG|得物技术
一、概述做后端开发调 BUG 有一个让人头疼的固定流程打开日志平台输入 traceId 或关键词搜日志从几十上百条日志里找到关键的那几条把日志里的类名、方法名复制出来去 IDE 里找对应代码结合代码逻辑判断哪里出了问题如果一次找不准回去再搜日志再翻代码……这个过程相对固定但非常耗时间。每次 BUG 定位光在日志平台和 IDE 之间来回切换就能消耗掉大半的时间。最开始在去年 Q3 想到这个问题的时候脑子里浮现的第一个方案是用 Cursor MCP把日志平台接进来再挂一个代码知识库让 AI 帮我查日志。但这个方案有缺陷 —— 日志查询是「动态的」它依赖环境、应用、时间范围没办法静态预置。此外这样处理没有办法做到比较丝滑地读代码、改代码。后来开始用 Claude Code接触到了 Skill 的概念可以在项目里定义一套自定义命令描述 AI 应该怎么执行这个命令的每个步骤于是整个思路变得清晰了。日志平台有 MCPClaude Code 有 Skill两者结合就能让 AI 自动完成「查日志 → 找关键信息 → 扫描代码 → 定位问题」这整个闭环。然后在 PM 的帮助下才有了 /log-diagnosis 这个 Skill。二、日志平台 MCP 是什么MCP 原理日志平台推出了基于 MCPModel Context Protocol协议的日志查询服务让 Claude 可以直接调用日志平台的能力无需人工在日志平台上手动查询。MCP 本质上是一种标准化的「工具调用协议」Claude Code 通过 SSEServer-Sent Events长连接与 MCP Server 通信实时获取日志数据。MCP 环境对照核心 MCP 工具鉴权流程secretKey日志平台后管申请 ↓ acquireTokenTool accessToken1小时有效最多同时存在5个 ↓ 携带 accessToken logsQuery / logSqlQuery / countLogTool ...secretKey 申请地址进入日志管理后台 → 日志权限 → 我的应用 → 生成密钥。三、/log-diagnosis Skill 是什么Skill 工作原理log-diagnosis 是一个运行在 Claude Code 里的自定义诊断命令。Claude Code 支持通过 .claude/skills/ 目录定义自定义技能Skill以 Markdown 文件描述行为规范Claude 在收到对应命令时会自动加载并执行。你只需要把 traceId 或告警信息告诉它剩下的全部交给 AI。完整执行链路如下用户输入 /log-diagnosis {环境} {代码分支} {诉求} ↓ Claude 加载 .claude/skills/log-diagnosis/SKILL.md ↓ 读取 .diagnosis/config.json 获取当前环境配置 ↓ 检查 accessToken 是否过期过期则自动刷新 ↓ 从 traceId 计算日志时间范围取第9-16位16进制时间戳 ↓ 调用日志平台 MCP 分页拉取全量日志最多20页不遗漏 ↓ 切换到指定代码分支结合日志关键词检索代码 ↓ 综合分析上游日志 当前服务日志 代码逻辑 → 根因 ↓ 生成诊断报告飞书文档 or 本地 Markdown ↓ 恢复原始代码分支两种诊断入口核心能力Token 自动管理accessToken 过期自动刷新无需手动维护分页全量拉取自动分页拉完所有日志禁止只查第一页就下结论最多 20 页跨服务分析自动识别上下游服务拉取关联服务日志交叉验证代码联动日志里出现的类名/方法名直接在代码里精确定位。queryString 语法规则# 格式 {field} {操作符} {值} {连接符} {field} {操作符} {值} # 操作符 : 精确匹配 ≈ : 模糊匹配like # 连接符 AND / OR / NOT # 示例 trace_id a1b2c3d4e5f6789012345678abcdef01 trace_id xxx AND log_level ERROR endpoint ≈ /api/your-endpoint AND log_level ERROR message ≈ timeout注意时间范围只通过 start/end 参数控制不要写在 queryString 中。四、安装与配置安装日志平台 MCPClaude Code在 Claude Code 命令行中执行按需安装对应环境# 测试环境 claude mcp add --transport sse dw-log-mcp-t1 https://{your-t1-aigw-domain}/api/v1/mcp/log-mcp/sse # 预发环境 claude mcp add --transport sse dw-log-mcp-pre https://{your-pre-aigw-domain}/api/v1/mcp/log-mcp/sse # 生产环境 claude mcp add --transport sse dw-log-mcp-prd https://{your-prd-aigw-domain}/api/v1/mcp/log-mcp/sse安装后重启 Claude Code执行 /mcp 确认连接状态正常。Cursor打开 Cursor Setting点击 Tools MCP添加 MCP Server添加 URLMCP Server 名称任意。建议按需安装 MCP Server避免额外消耗 token示例配置{ mcpServers: { dw-log-mcp-t1: { url: https://{your-t1-aigw-domain}/api/v1/mcp/log-mcp/sse }, dw-log-mcp-pre: { url: https://{your-pre-aigw-domain}/api/v1/mcp/log-mcp/sse }, dw-log-mcp-prd: { url: https://{your-prd-aigw-domain}/api/v1/mcp/log-mcp/sse }, dw-log-mcp-oversea-prd: { url: https://{your-oversea-aigw-domain}/api/v1/mcp/log-mcp/sse } } }返回设置就可以看到已经连接上。安装 /log-diagnosis Skill将 log-diagnosis 目录放到项目的对应目录下Claude Codeyour-project/ └── .claude/ └── skills/ └── log-diagnosis/ ├── SKILL.md # 技能行为规范核心 ├── README.md # 使用说明 └── reference.md # 附录时间脚本、queryString 示例等Cursoryour-project/ └── .cursor/ └── skills/ └── log-diagnosis/ ├── SKILL.md # 技能行为规范核心 ├── README.md # 使用说明 └── reference.md # 附录时间脚本、queryString 示例等配置 .diagnosis/config.json首次运行会自动引导创建直接调用 /log-diagnosisSkill 会一步步指示你给出 secret key也可手动在项目根目录创建 .diagnosis/config.jsonyour-project/ └── .cursor/ └── skills/ └── log-diagnosis/ ├── SKILL.md # 技能行为规范核心 ├── README.md # 使用说明 └── reference.md # 附录时间脚本、queryString 示例等字段说明secretKey唯一需要人工填写的字段在日志平台后管申请accessToken首次使用时由 AI 自动调用 acquireTokenTool 获取过期自动刷新accessTokenExpireAt从 acquireTokenTool 返回值自动填充fields调用 logFields 工具自动获取。五、使用方式命令格式/log-diagnosis {环境} {代码分支可选} {诉求描述}参数说明{环境}T1 / PRE / PRD按实际环境标识填写{代码分支}可选留空则使用当前分支{诉求描述}包含 traceId 或告警信息的问题描述用自然语言书写即可。示例# 用 traceId 定位接口异常 /log-diagnosis T1 feature/your-branch trace_id: your-trace 为什么最终没有返回数据 # 用告警信息分析错误原因 /log-diagnosis PRD master 告警详情【接口YourService/yourMethod】【业务码10002000】【业务码消息系统异常请稍后重试】帮我分析问题可能性一行命令AI 全程接管几分钟内给出根因分析。六、实战案例一个隐蔽的 SQL BUG背景某搜索接口在测试环境反馈没有返回数据。拿到 traceId直接执行/log-diagnosis T1 feature/your-branch trace_id: your-trace 为什么最终没有返回数据← 就这一句话接下来全部交给 AI。AI 自动拉取日志Skill 触发后AI 自动完成从 traceId 推算出日志时间范围2026-02-27 全天检查 accessToken 已过期自动刷新调用日志平台 MCP分 2 页拉取完整日志共 73 条。请求入参从日志自动提取{ assembleByOrg: true, channelType: MANUAL, orderNo: your-order-no, status: 1, ticketNo: your-ticket-no }AI 还原完整调用链路AI 自动识别出关键节点resultList is emptySQL 查询返回了空结果。问题在 DB 层而不在业务逻辑层。AI 提取组装后的查询 DTO从日志中提取到 toSearchDTO 组装结果{ channelType: MANUAL, customerTag: 1, deliveryMode: 某配送方式, orderStatus: 8010, orderType: 0, productCategoryIds: [29], status: 1, ticketSource: 67, ticketTypeId: 5802 }AI 从日志中提取实际执行的 SQL 发现根因ORM 框架在日志中打印了实际执行的 SQLAI 直接读取并分析SELECT a.id, a.pid, a.name, a.mode, a.status, a.org_id, a.org_ids, a.ticket_group_id, a.tenant_id, a.is_del, a.channel_types FROM your_type_table a LEFT JOIN your_relation_table b ON b.tenant_id 1 AND a.id b.type_id AND b.type 3 AND b.is_del 0 WHERE a.tenant_id 1 AND a.mode 2 AND a.is_del 0 AND a.status 1 AND (a.channel_types IS NULL OR a.channel_types OR FIND_IN_SET(MANUAL, a.channel_types) 0) AND (b.root_id is null or b.root_id in (29)) AND (a.order_types IS NULL OR a.order_types OR FIND_IN_SET(0, a.order_types) 0) AND (a.order_statuses IS NULL OR a.order_statuses OR FIND_IN_SET(8010, a.order_statuses) 0) AND (a.delivery_modes IS NULL OR a.delivery_modes OR FIND_IN_SET(某配送方式, a.delivery_modes) 0) AND (a.ticket_sources IS NULL OR a.ticket_sources OR FIND_IN_SET(67, a.ticket_sources) 0) AND (a.customer_tag IS NULL OR a.customer_tag 1) ← BUG 在此AI 发现其他字段都处理了 IS NULL 和 ‘’空字符串代表 “不限制”两种情况唯独 customer_tag 只判断了 IS NULL遗漏了空字符串 ‘’ 的情况。SQL 语义对比-- 其他字段正确IS NULL 和 都处理了 AND (a.order_types IS NULL OR a.order_types OR FIND_IN_SET(0, a.order_types) 0) AND (a.delivery_modes IS NULL OR a.delivery_modes OR FIND_IN_SET(某配送方式, a.delivery_modes) 0) AND (a.ticket_sources IS NULL OR a.ticket_sources OR FIND_IN_SET(67, a.ticket_sources) 0) -- customer_tag遗漏了 的判断← BUG AND (a.customer_tag IS NULL OR a.customer_tag 1)DB 中现有的数据customer_tag 字段都存的是空字符串未配置按业务语义本应匹配所有请求却因为这个遗漏被全部过滤掉了。AI 定位代码给出修复方案AI 在代码中直接找到对应的 MyBatis Mapper XML!-- 问题代码 -- if testcustomerTag ! null and (a.customer_tag IS NULL OR a.customer_tag #{customerTag}) /if !-- 修复后 -- if testcustomerTag ! null and (a.customer_tag IS NULL OR a.customer_tag OR a.customer_tag #{customerTag}) /if效率对比这个 BUG 的隐蔽性在于SQL 语法正确逻辑上也「看起来」没问题——只有对比了其他字段的写法才能发现 customer_tag 独自遗漏了空字符串的处理。这类细节差异人工排查很容易忽略AI 反而很擅长。七、诊断效率关键点有 traceId 时优先用 traceId 拉日志可精准获取单次请求的完整链路比关键词搜索精确得多关注关键日志节点toSearchDTO finished / search begins / resultList is empty / search finished 等快速判断数据在哪一层丢失SQL 打印日志ORM 框架输出是黄金线索直接反映最终执行的查询条件AI 能从中发现肉眼难以察觉的差异分页必须拉完日志平台一次只返回部分数据AI 会严格执行分页直到取完确保不遗漏关键日志。八、总结核心思路用「协议 规范」让 AI 接管固定流程这篇文章的本质是一次对重复性工程劳动的自动化尝试。调 BUG 的过程——查日志、提取关键信息、找代码、分析原因——逻辑固定步骤繁琐但并不需要太多创造性思维。这类工作恰好是 AI 最擅长接管的。实现这个闭环靠的是两个关键组合MCP让 AI 能够调用外部系统日志平台突破了「AI 只能处理静态上下文」的限制实现了对动态数据的实时获取。Skill给 AI 一份行为规范告诉它每一步该怎么做、先做什么后做什么、遇到什么情况怎么处理把「一次性对话」变成「可复用的工程化能力」。两者缺一不可。只有 MCPAI 能查日志但不知道怎么系统地分析只有 SkillAI 有流程但没有数据来源。组合起来才形成了真正可落地的闭环。值得借鉴的地方识别「固定流程」是自动化的起点不是所有工作都适合 AI 接管但凡是「步骤固定、信息来源明确、输出格式可预期」的工作都值得尝试用 Skill MCP 的方式来自动化。排查 BUG 是一个典型类似的还有代码审查、性能分析报告生成、告警巡检等。Skill 的本质是「给 AI 写操作手册」Skill 文件不是在「训练模型」而是在给 AI 一份清晰的 SOP。写得越细、约束越明确比如「禁止只查第一页就下结论」「必须分页拉完所有数据」AI 的执行质量越稳定。这和写给人看的文档本质上是一回事。AI 擅长发现「横向对比」类的 BUG本文的案例揭示了一个有意思的规律AI 在处理「同类字段逻辑不一致」这类问题时表现往往比人工更好。原因在于 AI 没有「先入为主」的经验偏见不会因为「这段代码看起来没问题」就跳过它会对所有字段做同等的审查。最后说一句AI 时代工程师的核心竞争力不只是「能写代码」更是「能把自己的经验和流程转化成可复用的 AI 能力」。/log-diagnosis 是一次小小的尝试但背后的思路值得在更多场景里延伸。往期回顾1.Redis 自动化运维最佳实践得物技术2.Claude在得物App数仓的深度集成与效能演进3.Claude Code OpenSpec 正在加速 AICoding 落地从模型博弈到工程化的范式转移得物技术4.大禹平台流批一体离线Dump平台的设计与应用得物技术5.基于 Cursor Agent 的流水线 AI CR 实践得物技术文 /阿程关注得物技术每周更新技术干货要是觉得文章对你有帮助的话欢迎评论转发点赞未经得物技术许可严禁转载否则依法追究法律责任。