关于 otel-instrumentation
使用 Kopai 添加并验证 OpenTelemetry 埋点的技能。它引导开发者完成埋点、生成流量、断言检查和故障排查,涵盖多种语言 SDK。
主要功能
- 01启动本地 Kopai 后端
- 02配置遥测环境变量
- 03为多种语言的服务添加埋点
- 04生成流量并验证遥测数据
- 05排查数据缺失或错误
适用场景
- 01为新服务添加遥测
- 02为现有代码补充上下文传播
- 03验证追踪、日志、指标和关闭流程
- 04诊断遥测数据未到达的问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ kopai-app/ kopai-mono --skill otel-instrumentation安装后在 Claude Code 中输入/otel-instrumentation确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
CHANGELOG.mdreferences/_sections.mdarchitectural-patterns.mdattributes.mdcli-reference.mdcontext-propagation.mdcustom-instrumentation.mddrive-traffic.mdinstrument-attributes.mdinstrument-errors.mdinstrument-spans.mdlang-cpp.mdlang-dotnet.mdlang-erlang.mdlang-fastify.mdlang-go.mdlang-java.mdlang-nextjs.mdlang-nodejs.mdlang-php.mdlang-python.mdlang-ruby.mdlang-rust.mdlayered-telemetry.mdnextjs-examples.mdotel-docs.mdsampling.mdsetup-backend.mdsetup-environment.mdtroubleshoot-missing-attrs.md详细介绍
使用 Kopai 进行 OpenTelemetry 插桩
发出宽事件,然后验证它们是否符合预期。
一个 Span 就是一个宽事件:一条扁平记录,包含某个工作单元的完整上下文。 Kopai 在 localhost 上运行,因此你无需盲目信任插桩——可以亲自通过应用发送流量,并验证收到的数据。validate-traces 中的所有断言都通过后,循环才算成功。只要还有任何断言未通过,这里的工作就尚未完成。
分支
| 你目前的情况 | 从这里开始 |
|---|---|
| 正在为没有遥测数据的服务进行设置 | 下方工作流的第 1 步 |
| 正在为现有代码库补充 OTel | 先阅读 context-propagation——这约占 60% 的工作——然后继续工作流 |
| 正在排查数据未送达的问题 | 阅读 troubleshoot-no-data,然后执行工作流的第 4 步 |
工作流
| # | 步骤 | 完成标准 |
|---|---|---|
| 1 | 启动后端 — npx @kopai/app start | curl -s -o /dev/null -w '%{http_code}' -X POST http://localhost:4318/v1/traces -H 'Content-Type: application/json' -d '{"resourceSpans":[]}' 返回 2xx |
| 2 | 配置环境 — setup-environment | 启动应用的 shell 中已导出 OTEL_EXPORTER_OTLP_ENDPOINT、OTEL_SERVICE_NAME 和 validation.run_id 运行标签 |
| 3 | 添加检测 — 按照下方 语言 SDK 中匹配的 lang-<language> 规则操作,然后配置判断规则 | 应用在加载 SDK 后启动,且不打印 OTel 导出错误 |
| 4 | 自行发送流量 — drive-traffic | 每个发现的入口点都至少调用一次,并且至少主动触发一次故障 |
| 5 | 断言 — validate-traces,然后是 validate-logs、validate-metrics 和 validate-shutdown | 所有断言均通过。循环状态为绿色 |
| 6 | 修复 — 按照下方 修复方法 中匹配的 troubleshoot-* 规则操作 | 返回步骤 4 并重新发送流量。断言未通过时,绝不要停止 |
步骤 4–6 是一个循环,而非顺序流程。只有在同一次运行中,针对步骤 4 发送的流量通过步骤 5 的验证后,才能报告检测已完成。
什么情况值得创建 span
由两个问题决定:
- 有意义吗? — 这项工作是否会显著影响请求的延迟或失败情况?
- 可聚合吗? — 按名称和属性分组后,是否能得出有用的趋势?
两个答案都是“是” → 创建 span。否则 → 在已有的 span 上添加属性。
拿不准时,优先使用属性,而不是子 span。父 span 上的属性无需 JOIN,查询时不增加额外开销,而且可以立即分组。完整的决策表以及三种常见错误,请参阅 instrument-spans。
核心模式
一个跨度、丰富的属性、明确的错误状态。以下示例使用 Node.js;所有语言都遵循相同的结构——请参阅下方 语言 SDK 中对应语言的规则:
import { trace, SpanStatusCode } from "@opentelemetry/api";
const tracer = trace.getTracer("checkout");
export async function processPayment(order: Order) {
return tracer.startActiveSpan("process-payment", async (span) => {
try {
span.setAttributes({
"order.id": order.id, // IDs are attributes, never span names
"order.total": order.total,
"payment.provider": order.provider,
});
const receipt = await charge(order);
span.setAttribute("payment.status", receipt.status);
return receipt;
} catch (err) {
span.recordException(err as Error);
span.setStatus({
code: SpanStatusCode.ERROR,
message: (err as Error).message,
});
throw err;
} finally {
span.end();
}
});
}
custom-instrumentation 中提供了每种模式的完整代码,包括嵌套跨度、异步扇出、队列和手动上下文。
命名
- 跨度名称描述操作:
GET /api/users、db.query SELECT、process-payment - 属性名称使用点号命名空间:
user.id、order.total、cache.hit - 对于标准内容,遵循 OTel 语义约定:
http.route、db.system、rpc.service - 为自定义扩展添加命名空间:
app.、checkout.、<company>.
跨度名称必须具有低基数。绝不要将 ID 插入跨度名称——ID 应放在属性中。
选择检测包
首先检测项目使用的包管理器:如果 package.json 中存在 packageManager 字段,则以该字段为准;否则根据锁文件判断——pnpm-lock.yaml → pnpm,yarn.lock → yarn,bun.lock → bun,package-lock.json → npm。所有安装操作都使用该包管理器——第二个包管理器会生成另一份锁文件,并在不知不觉中造成差异。npx @kopai/cli 验证命令不受包管理器限制;npx 随 Node 一同提供,且不会触碰项目的依赖树。
检查弃用状态时,应查询注册表,而不是查看安装输出——只有 npm 会在安装时打印完整的弃用警告;pnpm 会截断警告,Yarn 4 则完全不打印。如果 npm 打印了警告,请仔细阅读:绝不要通过 tail、grep -v 或 --quiet 过滤安装输出。
npm view @opentelemetry/instrumentation-<lib> deprecated # empty output = not deprecated
npm view 只读取注册表,在 pnpm/yarn 项目中也能使用(npm 随 Node 一同提供);对应的原生命令是 pnpm view <pkg> deprecated 和 yarn npm info <pkg> --fields deprecated --json(Yarn 4)。
弃用消息通常会指出替代方案——使用它,绝不要使用已弃用的包;如果没有指出替代方案,请遵循该包自己的迁移指南,而不要猜测。当框架团队发布自己的插件时(Fastify → @fastify/otel),优先使用该插件,而不是 contrib 包:它通过框架的插件系统注册,不会拦截 require/import——原生 ESM 导入会绕过此类拦截,除非添加实验性的加载器钩子。
规则
按任务范围划分的规则文件。仅在工作流指向某个文件时加载它。
设置 — setup-backend、setup-environment
语言 SDK — lang-nodejs、lang-fastify、 lang-nextjs、 lang-python、lang-go、 lang-java、lang-dotnet、 lang-ruby、lang-php、 lang-rust、lang-erlang、 lang-cpp
需要埋点的内容 — instrument-spans(哪些操作值得创建 span)、
instrument-attributes(哪些属性、时间属性、异步摘要)、
instrument-errors(error、span 状态、slug)、
context-propagation(上下文传递;框架访问器的注意事项)、
layered-telemetry(trace、metric 与 log 的区别)、
sampling
验证效果 — drive-traffic(自行生成流量)、 validate-traces、validate-logs、 validate-metrics、validate-shutdown
修复问题 — troubleshoot-no-data、 troubleshoot-missing-spans、 troubleshoot-missing-attrs、 troubleshoot-wrong-port
参考资料
深入了解 — 仅在任务需要时加载:
- attributes — 按类别整理的规范属性目录
- custom-instrumentation — 各语言中每种模式的完整代码
- architectural-patterns — 队列、异步扇出、ETL、无服务器
- cli-reference — Kopai CLI 命令
- nextjs-examples — Next.js 埋点示例
- otel-docs — OpenTelemetry 文档链接
相关技能
- otel-genai-instrumentation — 大模型、Agent 和工具调用埋点
- root-cause-analysis — 排查遥测数据开始流动后的问题。埋点时应考虑该技能提出的问题:谁受到了影响、发生了什么变化、时间花在了哪里
- create-dashboard — 将此处发出的信号可视化