mcpField
O
opentelemetry

opentelemetry

github.com/mizchi云与 DevOps41644 次安装2 周前更新
代码仓库

关于 opentelemetry

介绍 OpenTelemetry 核心实践的技能,涵盖信号选择、Span 设计、上下文传播、采样和 OTLP 导出。适合实现或排查跨服务遥测的开发者,并说明常见埋点错误。

主要功能

  1. 01追踪、指标与日志的选择
  2. 02Span 命名、属性、事件和错误处理
  3. 03W3C 上下文传播
  4. 04采样策略指导
  5. 05OTLP 导出器配置与常见问题

适用场景

  1. 01为应用选择合适的遥测信号
  2. 02设计分布式请求的 Span
  3. 03排查追踪上下文中断或导出缺失

安装

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

$npx skills add https://github.com/mizchi/skills --skill opentelemetry

安装后在 Claude Code 中输入/opentelemetry确认已加载。

附带文件README.md

详细介绍

OpenTelemetry — 核心模式

信号选择

编写代码前,先选择合适的信号:

信号适用场景成本
Traces请求生命周期、延迟归因、分布式因果关系高(每个请求)
Metrics聚合计数、速率、直方图——仪表板和告警低(预先聚合)
Logs带上下文的离散事件——错误、审计、调试中

经验法则:指标回答“频率有多高/速度有多快”,日志回答“发生了什么”,追踪回答“为什么”。指标足以解决问题时,不要使用追踪。

Span 设计

命名约定
<verb> <noun>         →  "fetch user", "send email"
<provider>.<operation> →  "db.query", "http.get", "cache.set"

切勿在 span 名称中放入可变数据(ID、值)——请改用属性。Span 名称是追踪索引中的基数键。

属性
span.setAttributes({
  "db.system": "sqlite",
  "db.operation": "select",
  "db.sql.table": "users",
  "user.id": userId,          // high-cardinality: OK as attribute, not in name
});

请遵循 OpenTelemetry 语义约定 中广为人知的属性名称(http.*、db.*、rpc.* 等)——后端和 APM 都会依赖这些名称。

事件与子 Span
  • 事件:当前操作中的瞬时点(span.addEvent("cache_miss"))
  • 子 Span:有自己的持续时间,延迟很重要,适合用于追踪瀑布图
状态与异常
span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
span.recordException(err);  // adds exception.type / exception.message / exception.stacktrace

发生错误时,两者都要调用。单独调用 recordException 不会将状态切换为 ERROR——Span 在界面中仍会显示为成功。

确保调用 span.end()
// ✓ callback form guarantees end()
tracer.startActiveSpan("operation", (span) => {
  try {
    return doWork();
  } catch (e) {
    span.recordException(e as Error);
    span.setStatus({ code: SpanStatusCode.ERROR });
    throw e;
  } finally {
    span.end();
  }
});

未结束的 Span 会滞留在处理器队列中,可能永远不会导出。

上下文传播

W3C TraceContext(traceparent / tracestate)是标准规范。在传出请求时注入,在传入请求时提取:

import { propagation, context } from "@opentelemetry/api";

// Outgoing HTTP
const carrier: Record<string, string> = {};
propagation.inject(context.active(), carrier);
fetch(url, { headers: carrier });

// Incoming (server handler)
const ctx = propagation.extract(context.active(), request.headers);
tracer.startActiveSpan("handle request", { context: ctx }, (span) => {
  // span is now a child of the upstream trace
});

最常见的错误:创建 Span 时没有提取传入上下文 → 追踪瀑布图会断裂成互不相连的根 Span。启动根服务器 Span 之前,务必先提取上下文。

采样

策略使用时机
AlwaysOn开发环境/低流量预发布环境
TraceIdRatioBased(0.1)高流量生产环境——对 10% 的新追踪进行采样
ParentBased(root: TraceIdRatioBased)推荐的默认策略——遵循上游决策,并按比例对新的根 Span 采样
尾部采样(OTel Collector)无论头部采样决策如何,都需要完整保留所有错误

ParentBased 可避免上游对追踪进行采样、下游却将其丢弃的故障情形(瀑布图断裂)。

OTLP 导出器配置

import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";

const exporter = new OTLPTraceExporter({
  url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT + "/v1/traces",
  headers: { Authorization: `Bearer ${process.env.OTEL_API_KEY}` },
});

provider.addSpanProcessor(
  new BatchSpanProcessor(exporter, {
    maxQueueSize: 512,
    scheduledDelayMillis: 2000,
    exportTimeoutMillis: 10_000,
  })
);

生产环境中请使用 BatchSpanProcessor——它是异步的,开销也很低。SimpleSpanProcessor 会阻塞事件循环;仅用于本地调试。

常见问题

  • 未调用 provider.register():SDK 已配置,但没有任何内容被导出。请在任何插桩运行前调用。
  • ESM + 自动插桩(Node.js):require-in-the-middle 钩子不会对 ESM 静态导入触发。解决方法请参阅 otel-node。
  • Cloudflare Workers:没有 Node.js 运行时,需要进行 fetch 边界插桩。请参阅 cloudflare-workers-otel-utels。
  • Span 名称包含动态数据:会导致追踪索引基数激增。请改用属性。
  • 出站调用未使用 W3C 传播:分布式追踪会断裂——下游 Span 会显示为孤立的根 Span。

评论

支持 Markdown