mcpField
O
otel-onboarding-style

otel-onboarding-style

github.com/superloglabs云与 DevOps13373 次安装21 周前更新
代码仓库

关于 otel-onboarding-style

定义服务 OpenTelemetry 埋点规范的技能,涵盖信号、资源属性、错误、HTTP 框架和 LLM 提供商,帮助统一遥测配置方式。

主要功能

  1. 01原生 OpenTelemetry API 指引
  2. 02资源与环境属性规范
  3. 03Trace、日志和指标实践
  4. 04HTTP 与错误埋点
  5. 05LLM 提供商遥测指引

适用场景

  1. 01为服务配置遥测
  2. 02建立按操作划分的 RED 信号
  3. 03添加与 Trace 关联的结构化日志
  4. 04埋点受支持的 LLM 提供商

安装

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

$npx skills add https://github.com/superloglabs/skills --skill otel-onboarding-style

安装后在 Claude Code 中输入/otel-onboarding-style确认已加载。

详细介绍

OTel 接入规范

使用原生 OpenTelemetry API。不要自行发明辅助 API。

在 TypeScript/JavaScript 中,对于范围明确的业务 Span,使用已发布的 @superlog/otel-helpers withSpan 辅助函数;如果 package.json 中尚未包含 @superlog/otel-helpers,请将其添加进去。 只要可以安装该包,就必须使用它。withSpan 用于替代将整个函数改写为 tracer.startActiveSpan(...) 加上 try / catch / finally 的做法。对于 OpenInference/提供方检测可以直接观测到的提供方 SDK 调用,不要使用辅助函数进行包装。

应该:

const tracer = trace.getTracer("mugline.api");
const meter = metrics.getMeter("mugline.api");
const ordersSubmitted = meter.createCounter("orders.submitted");

await withSpan("order.submit", async (span) => {
  span.setAttributes({
    "tenant.id": tenantId,
    "order.id": orderId,
    outcome: "success",
  });
  ordersSubmitted.add(1, { "tenant.id": tenantId, outcome: "success" });
}, { tracer });

不应该:

await sendSuperlogSpan(...);
recordCounter(...);
withTelemetry(...);

命名

  • 文件/函数应与提供方无关:telemetry.ts、observability.ts、 initTelemetry()、initObservability()。
  • 仅在端点/密钥设置注释或 PR 说明中使用 Superlog 一词。
  • Span 名称应符合惯例且基数较低:checkout.process、voice.session、 llm.generate_copy。
  • 优先使用具有语义的产品操作 Span 名称,而非提供方传输名称。 llm.generate_copy 或 llm.voice_response 通常比 llm.anthropic.messages.create 更有用。

端点和公开令牌

在引导源代码中直接内联端点和 Superlog 公开摄取令牌。该令牌以 sl_public_ 开头,限定于单个项目且仅可写,适合放在浏览器/移动端/服务器源代码中, 安全性类似 PostHog 项目令牌或 Sentry DSN。

SUPERLOG_ENDPOINT = "https://intake.superlog.sh"
SUPERLOG_PUBLIC_TOKEN = "sl_public_…"

不要自行编造旧名称,例如 SUPERLOG_API_KEY 或 SUPERLOG_INTAKE_URL, 即使是文档或注释中的占位文本也不行。在配对流程进行期间,请在源代码中使用生成的 sl_public_ 令牌;在注册意向流程将其关联到用户项目之前,摄取操作可能会拒绝该令牌。

通过导出器构造函数的 endpoint / headers 选项,显式将内联值传递给 SDK。 不要通过隐式读取 OTEL 环境变量来配置 Superlog;缺少环境变量是本规范要避免的 主要接入失败原因。

令牌应放在 x-api-key 请求头中。摄取端仅接受 x-api-key: <token> 或 Authorization: Bearer <token>(必须包含字面前缀 Bearer )—— 优先使用 x-api-key。即使令牌有效,使用其他请求头名称也会导致每个请求都返回 401; 这是仅次于缺少环境变量的第二常见接入失败原因。定义一个单行辅助函数, 将请求头名称集中在一处:

function superlogHeaders(token: string): Record<string, string> {
  return { "x-api-key": token };
}
def superlog_headers(token: str) -> dict[str, str]:
    return {"x-api-key": token}

如果仓库可以从多个路径调用遥测初始化,请保护提供方/导出器设置,避免重复导入、测试、 热重载或框架回调安装重复的处理器或日志处理程序。对于可正常启动的单入口点应用, 保持实现简单。

当值可用时,请包含标准资源属性: service.name、service.version、deployment.environment.name,以及下方的 VCS 属性。

环境标记

尽可能为每个信号添加运行时环境标记。优先在 OTel 资源上设置一次 deployment.environment.name,使其传播到追踪、日志和指标。根据现有平台环境变量推断环境, 例如 NODE_ENV、VERCEL_ENV、RAILWAY_ENVIRONMENT_NAME、 FLY_APP_NAME/发布元数据、ENVIRONMENT、APP_ENV 或 PYTHON_ENV; 将明显的值规范化为基数较低的名称,例如 local、development、preview、staging 和 production。

如果某个运行时/导出器路径无法为所有可观测信号附加资源属性,请手动将相同的低基数环境值 添加到自定义 Span 属性、日志记录和指标数据点。除非仓库已有标准,否则不要创建 env、environment 或 app.environment 等独立属性名称;在 SDK 允许的情况下, 统一使用 deployment.environment.name。

VCS 资源属性

为每个已插桩服务在 OTel 资源上设置 vcs.repository.url.full。其值应为仓库规范的 https URL(例如 https://github.com/acme/api)——即用户会粘贴到浏览器中的同一个 URL,而不是 SSH URL,也不是本地工作树路径。这一点至关重要:它能让 Superlog 将遥测数据关联回事实来源。可以在 SDK 初始化时将此字符串与 service.name 一起硬编码;如果构建环境已提供仓库标识(例如 VERCEL_GIT_REPO_OWNER + VERCEL_GIT_REPO_SLUG、RAILWAY_GIT_REPO_OWNER + RAILWAY_GIT_REPO_NAME),则优先从环境变量读取,以免分叉或重命名导致信息不一致。

还应尽力设置 vcs.ref.head.revision(提交 SHA)。从运行时/构建平台已注入的任意环境变量中读取: VERCEL_GIT_COMMIT_SHA、RAILWAY_GIT_COMMIT_SHA、GITHUB_SHA、 SOURCE_COMMIT、GIT_COMMIT、HEROKU_SLUG_COMMIT 等。不要在运行进程中通过 shell 调用 git——许多生产镜像中没有 git 或工作树。如果没有可用的环境变量来源,请省略该属性;不提供 SHA 没关系,不提供 URL 则不行。

请严格使用 vcs.repository.url.full 和 vcs.ref.head.revision 这两个名称——它们是 OTel 语义约定中的键。不要另行发明 git.repo 或 app.repo_url 之类的属性。

信号

每个已插桩服务的基线目标,是按软件组件采集 RED 指标:操作次数、错误次数和操作耗时。必须满足以下两点:

  • 每个信号都要设置 service.name,以便按服务汇总 RED 指标。
  • 每个不同的工作单元都要生成独立的 span/指标序列,并带有低基数操作标识符,例如 HTTP 路由模板、队列处理器名称、定时任务名称、RPC 方法等。必须能够按操作查询 RED 指标,而不只是按服务查询。

如果某个服务没有针对其主要工作(入站 HTTP 请求、队列处理器、定时任务、后台循环等)按操作生成这三项指标的机制,则该服务的接入尚未完成。

  • 链路追踪:所有关键操作都要有带相关属性的 span。每个服务的每个入站工作单元至少要有一个 span——通常由 HTTP/框架自动插桩生成,否则就在请求/处理器入口处手动接入 withSpan(或对应语言中的等效机制)。
  • 日志:采用结构化格式,简洁明了,通过 OTLP 转发,并与 trace/span 关联。
  • 指标:为关键操作采集低基数计数器/直方图。
  • 尽可能包含租户/组织/项目相关信息。
  • 除非仓库已将原始用户 ID 或请求 ID 视为有界的类租户 ID,否则不要将其放入指标标签。

HTTP 和框架插桩

为每项服务安装与其语言和框架对应的标准 OpenTelemetry HTTP/服务器插桩(例如,Node 中的 @opentelemetry/instrumentation-http 加上框架包,Python 中的 opentelemetry-instrumentation-fastapi/-django/-flask 等),并在缺少时将其添加到 package.json/pyproject.toml。这会填充 http.server.request.duration、http.request.method 和 http.response.status_code,让 RED 无需按路由编写代码即可正常工作。

如果服务使用的框架或运行时没有可用的自动插桩(自定义服务器、特殊运行时、通过非 HTTP 传输的 RPC、后台工作器循环),则应在入口点手动接入 span,确保每个工作单元都生成一个带有 http.* 或适用于该操作的属性及状态的 span。不要以服务“只有业务 span”为由跳过此步骤——这类 span 无法提供按服务划分的 RED 指标。

错误

每个表示工作单元的跨度都必须以一致的方式报告失败,以便能够推导错误计数:

  • 捕获到异常时,调用 span.recordException(err) 和 span.setStatus({ code: SpanStatusCode.ERROR, message })(或该语言中的 等效写法)。HTTP 5xx 通常由自动插桩处理;但对于已处理的错误和手动接入的跨度,仍需执行这些操作。
  • 在业务跨度和对应的指标数据点上设置 "success" 或 "error" 的 outcome 属性,这样无需按状态码关联数据,单个低基数维度就能将 RED 拆分为成功与错误。
  • 对于已知的错误类别,还要将 error.type 设为简短的低基数字符串(例如 "timeout"、"validation"、"upstream_5xx")。不要使用异常消息,因为其取值范围不受限制。
  • 不要在 withSpan 回调中悄悄吞掉异常;记录后重新抛出,这样外围跨度和调用方都能感知失败。

大模型指标

如果应用使用大模型,首先查看是否已有供应商插桩能够捕获模型、供应商、令牌和错误跨度。在 JavaScript/TypeScript 中,对于受支持的 SDK,优先使用 OpenInference 包,例如 @arizeai/openinference-instrumentation-anthropic。保持实际的供应商调用原生且易读。

const response = await client.messages.create({
  model,
  max_tokens: 100,
  messages,
});

每个供应商调用点仍需提供足够的遥测信息,以便解答使用情况相关的问题。如果供应商插桩支持捕获模型、供应商和令牌跨度,就由它负责。不要在每个应用调用点重复这些属性,也不要在产品处理程序中加入供应商定价表或成本计算。Superlog 会在 UI/查询层根据捕获的供应商、模型和令牌数据,集中计算大模型的估算成本。

llmInputTokens.add(inputTokens, {
  "tenant.id": tenantId,
  "gen_ai.provider.name": "anthropic",
  "gen_ai.request.model": model,
  "app.gen_ai.use_case": "voice.initial_greeting",
  "app.gen_ai.call_site": "_callMugCopyLlm",
  outcome: "success",
});

仅当供应商插桩无法捕获令牌用量时,才使用计数器统计累加总量:

  • llm.tokens.input
  • llm.tokens.output

令牌计数器使用 unit="tokens" 或 SDK 中的等效写法。如果 OpenInference/供应商插桩已经捕获令牌用量,就不要为了保持一致而重复添加令牌计数器。对于常规大模型调用,不要添加 llm.cost_usd 或类似的应用侧成本指标;成本应由 Superlog 的集中定价层处理。

使用直方图表示延迟/耗时分布。

对于大模型供应商/模型/令牌属性,优先使用当前的 gen_ai.* 语义约定风格属性名称;对于用例和调用点等有界应用维度,使用 app.gen_ai.*。避免另行发明 llm.* 属性,除非代码仓库已统一采用这些属性。

如果应用调用 OpenAI、Anthropic 和 Google 的服务,则应为这三者全部添加插桩。

冒烟检查

当代码仓库中有合适的位置时,应添加持久的冒烟检查入口,例如 README、TESTING 指南、脚本、npm 命令、pytest 或已检入的命令说明。

冒烟检查应明确验证:在存在 OTel 环境变量的情况下,启动/导入过程能够顺利完成,从而确保供应商配置、导出器构造、日志桥接和框架插桩均可无错误地初始化。然后,在条件允许时,执行一次实际的插桩跨度/日志/指标操作,或尝试进行 OTLP 导出。通用健康检查路由只能证明服务器能够响应;应优先选择能够经过所添加插桩的操作。

评论

支持 Markdown