mcpField
S
superlog-onboard

superlog-onboard

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

关于 superlog-onboard

用于为仓库中的所有可运行服务接入 OpenTelemetry,并将追踪、日志和指标发送到 Superlog 的编码技能。它规定使用原生 SDK 启动遥测,并处理项目级公开令牌。

主要功能

  1. 01盘点可运行应用与服务
  2. 02配置原生 OpenTelemetry SDK
  3. 03导出追踪、日志和指标
  4. 04将应用日志桥接到 OTLP
  5. 05设置服务与仓库属性
  6. 06处理 Superlog 公开写入令牌

适用场景

  1. 01为多服务仓库接入 Superlog
  2. 02为移动端和边缘服务添加遥测
  3. 03配置日志与当前跨度关联
  4. 04检查导出器请求头和接收配置

MCP 相关

此技能指导应用将 OpenTelemetry 追踪、日志和指标导出到 Superlog,并说明遥测导出器使用的端点和公开令牌请求头。

安装

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

$npx skills add https://github.com/superloglabs/skills --skill superlog-onboard

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

详细介绍

Superlog 接入

将 OpenTelemetry 跟踪、日志和指标接入用户的项目,使遥测数据流向 Superlog。覆盖仓库中的每个应用和服务,而不仅仅是用户当前所在的应用。

优先使用原生 OpenTelemetry API 和框架文档中说明的引导方式,而不是自定义辅助层。如果遇到特定技术栈的问题,请查阅该语言的 OTel 文档,不要凭猜测。

编辑前,请阅读适用的配套技能:

  • otel-onboarding-style,了解通用 OTel 风格。
  • otel-python-style,适用于 Python 服务。
  • otel-fastapi-style,适用于 FastAPI 服务。
  • otel-livekit-style,适用于 LiveKit Agent。
  • otel-nextjs-style,适用于 Next.js/Vercel 应用。
  • otel-expo-style,适用于 Expo / React Native 应用。
  • otel-supabase-edge-style,适用于 Supabase Edge Functions。
  • otel-generic-style,适用于其他任何语言(Go、Java/Kotlin、Ruby、Rust、.NET/C#、PHP、Elixir、纯 Node 等);若以上均不适用,则使用此项作为后备方案。

步骤 0 — 端点和公开令牌处理

OTLP 端点始终为 https://intake.superlog.sh,并直接写入引导代码。

Superlog 公开写入令牌以 sl_public_ 开头。它限定于项目、仅可写入,并且有意设计为可安全地包含在应用程序源码中,包括浏览器和移动端构建产物。将其视同 PostHog 项目令牌、Sentry DSN 或 Datadog RUM 客户端令牌:它可以向一个项目发送遥测数据,但无法读取数据、更改设置或访问 Superlog 帐户。

将公开令牌内联为与端点相邻的常量。不要将其放入 .env 文件、部署设置或生成的 shell 命令中;源码级配置是预期的接入方式,也能避免因缺少环境变量导致部署失败。

如果 OTLP 导出器需要请求头,请通过导出器构造函数将公开令牌作为 x-api-key 请求头传入。这是接入失败最常见的原因:令牌有效,但导出器使用了错误的请求头名称(或根本没有发送请求头),因此每个请求都会收到 401,导致安装看似失败,而实际上密钥没有问题。写入端只从两个位置读取令牌——x-api-key: <token>,或 Authorization: Bearer <token>(必须包含字面上的 Bearer 前缀)。请使用 x-api-key;它可以避免 Bearer 前缀陷阱,也能兼容会剥离 Authorization 的代理/SDK。不要使用其他请求头名称(api-key、x-superlog-token、不带 Bearer 的 Authorization: <token>)——这些方式都会返回 401。

将其封装为单行辅助函数,让请求头名称只出现在一个位置,并且定义该辅助函数——绝不要调用未定义的 superlogHeaders:

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}

两个处理路径,无需提问:

提示词中包含公开令牌

如果调用提示词中包含 sl_public_... 令牌,请验证其前缀,并将其内联到你编写的每个遥测引导文件中。不要在聊天中输出完整令牌;它会像其他公开客户端令牌一样显示在代码差异中。

无公开令牌

在本地生成一个公开令牌,立即注册一个注册意向,然后并行继续操作——不要因为注册而阻塞安装。

  1. 在本地生成一个随机的明文公开摄取令牌,格式为 sl_public_<base64url-ish random bytes>。前缀之后至少使用 32 字节的熵。将明文保存在内存中,以便内联到引导文件中,但绝不要在聊天中完整打印令牌。

  2. 计算 keyHash = sha256(plaintextToken),结果为小写十六进制;计算 keyPrefix = 令牌前缀加上前缀之后的前 6 个令牌字符。

  3. 使用 Content-Type: application/json,向 https://api.superlog.sh/api/signup-intents 发送 POST 请求,请求体如下:

    {
      "keyHash": "<sha256 hex>",
      "keyPrefix": "<short public token prefix>",
      "returnTo": null
    }
    

    如果 Agent 运行时提供了返回当前对话的安全返回链接/深层链接,请将其作为 returnTo 传入;否则使用 null。绝不要在此请求中放入明文令牌。

  4. 响应中包含 id、signupUrl 和 expiresAt。在用户的默认浏览器中打开 signupUrl(open "$signupUrl" / xdg-open "$signupUrl" / start "" "%signupUrl%"),并在聊天中打印该 URL。简要说明注册标签页已打开(GitHub/Slack 集成会在那里完成),并且安装将在最后检查摄取状态——无需打断用户当前的流程。

  5. 不要等待注册完成。 使用生成的明文令牌作为引导源,继续执行步骤 1–4。步骤 4 是关卡:它会发送真实遥测数据,并根据响应代码判断用户是否仍需完成注册。

步骤 1 — 列出仓库中的每个应用/服务

在进行任何埋点之前,先全面检查项目。检查工作区清单(pnpm-workspace.yaml、根目录 package.json 中的 workspaces、go.work、Cargo 工作区、Python pyproject.toml 工作区配置,以及 apps/* 和 services/* 约定)。识别每项服务:Web 前端、API、工作进程、后台任务、CLI、示例/演示应用、移动应用、Supabase 和/或服务端函数。移动应用和无服务器/边缘函数都在范围内;不要仅仅因为它们是客户端或生命周期短就跳过。没有运行时入口点的纯类型/配置包可以跳过。不要跳过任何可运行的服务,也不要将其留作“范围之外”:本次运行要为所有内容添加埋点,可能不会有后续操作。

开始前先向用户展示列表,以便他们提出更正。

步骤 2 — 为每项服务安装原生 OTel 并进行引导

使用该语言的原生 OpenTelemetry SDK。 如果存在官方包,不要使用供应商封装或手写辅助工具。例如,“原生”包括:Node 服务使用 @opentelemetry/sdk-node,常规 Next.js/Vercel 应用使用 @vercel/otel(sdk-node 会破坏 Next 的 webpack,且会错过框架引导),Vite/SPA/Expo 使用 @opentelemetry/sdk-trace-web 和兼容浏览器/移动端的导出器,Python 使用 opentelemetry-instrumentation-* 和 opentelemetry-sdk,Go 使用 go.opentelemetry.io/otel。

不要使用通用封装 API。避免使用 sendSuperlogSpan、recordCounter、recordLog、startTelemetrySpan 或 withTelemetry 之类的可复用辅助工具。在模块作用域中获取原生 tracer/meter/logger,并直接使用 SDK 自带的 API。在 TypeScript/JavaScript 中,为有边界的业务 span 使用已发布的 @superlog/otel-helpers withSpan 辅助工具,并将 @superlog/otel-helpers 添加到 package.json;只要该包可以安装,这就是必需的,因为它可避免将整个函数扩展为 startActiveSpan 加 try/catch/finally。对于 OpenInference/供应商埋点能够直接观察到的供应商 SDK 调用,不要使用辅助工具包装。如果边缘运行时确实无法加载上游 OTel SDK,请保持 shim 精简、与供应商无关且遵循 OTel 形式:tracer.startActiveSpan、span.setAttributes、SpanStatusCode、meter.createCounter、histogram.record。 连接全部三种信号——追踪、日志和指标。日志通过 OTLP 发送,而不只是写入 stdout——为所用语言配置 OTel 日志桥接,使应用日志(保留现有日志级别和结构化字段)自动携带当前的 trace_id / span_id。用户现有的日志记录器继续正常工作;你只需在底层添加 OTLP 处理器/处理程序。

日志桥接不可省略,也不能仅靠 SDK 初始化来实现——大多数语言 SDK 和框架封装默认会接入追踪(有时也包括指标),但需要显式配置 LoggerProvider + OTLP 日志导出器 + 日志记录处理器 + 连接到现有日志记录器的桥接。示例:Python 标准库需要 LoggerProvider + OTLPLogExporter + 附加到根日志记录器的 LoggingHandler(还需要 LoggingInstrumentor,才能让现有记录关联追踪);Node 需要 @opentelemetry/sdk-logs + 项目日志记录器(pino/winston/bunyan)的插桩;@vercel/otel 需要 logRecordProcessor(s) 选项——没有它,日志就不会离开进程。配套的风格技能会详细说明各技术栈所需的具体配置——请阅读。

需要主动检查的常见日志桥接错误:

  • 处理器附加到了具名日志记录器,但应用使用的是根日志记录器(反之亦然)——没有日志会流出。
  • 默认级别过滤器(例如 WARNING)吞掉了用户实际想在 Superlog 中查看的 INFO/DEBUG 日志。
  • BatchLogRecordProcessor 在关闭时未刷新 → 短生命周期 CLI、无服务器和边缘函数会丢弃最后一批日志。将 shutdown() / forceFlush() 接入运行时的退出钩子。
  • 保留现有供应商传输(Pino → Logtail、Winston → Datadog 等)完全没问题,也是预期做法——但要确保桥接来自日志记录器,而不是再添加第二个传输,通过不同的格式化器重复发送同一行日志。
  • 在任何 span 之外发出的日志不会携带 trace_id / span_id。这是正确且预期的行为;不要为此在日志调用周围创建一次性 span。

引导规则:

  • 引导文件必须在导入任何框架之前运行。使用语言/框架文档指定的钩子(--import 标志、instrumentation.ts、在 main.py 顶部导入等)。
  • 在引导源代码中直接写入端点(https://intake.superlog.sh)和公开的写入令牌。不要读取 process.env.OTEL_EXPORTER_OTLP_*,也不要编写任何 .env 文件。(各技术栈的具体写法请参阅对应的框架风格技能。)
  • 使用 HTTP OTLP 导出器,不要使用 gRPC。gRPC 会引入原生绑定,导致打包器出错并增加容器配置的复杂度。
  • 使用项目现有的包管理器(根据锁文件判断)。
  • 优先采用幂等的修改。如果配置文件已存在,应修改而不是覆盖。
  • 为每个服务在 OTel 资源上设置资源属性:service.name、service.version、deployment.environment.name 和 vcs.repository.url.full——仓库的规范 https URL(例如 https://github.com/acme/api)。仓库 URL 尤其重要,可以和 service.name 一起直接写入 SDK 初始化代码;如果构建平台提供了 slug(Vercel 的 VERCEL_GIT_REPO_OWNER/VERCEL_GIT_REPO_SLUG、Railway 的 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。可以不设置 SHA,但不能不设置 URL。请严格使用 OTel 语义约定中的键,不要自创 git.repo / app.repo_url。 框架规则:
  • Next.js/Vercel:使用 instrumentation.ts 和 @vercel/otel 的 registerOTel(...) 进行引导。除非仓库已采用 @opentelemetry/sdk-node / NodeSDK 引导架构且你正在扩展该架构,否则不要改用这种原始引导方式。仅在自动检测无法覆盖的路由处理程序中使用 @opentelemetry/api 的追踪器/计量器。registerOTel 默认不会导出日志——请使用来自 @opentelemetry/exporter-logs-otlp-http 的 OTLPLogExporter,并传入 logRecordProcessor(v1)/logRecordProcessors(v2);否则日志不会离开进程。选项名称须与已安装的 @vercel/otel 主版本匹配。
  • **Expo/React Native:**保留现有的 Expo Go/不支持运行时的保护逻辑。在受支持的构建中,于 Sentry 之前以及应用注册/用户代码运行之前调用 initObservability()。在可观测性模块中内联端点和 sl_public_ 令牌;不要为 Superlog 使用 EXPO_PUBLIC_* 环境变量。
  • **Supabase Edge Functions:**目前,原生 Deno OpenTelemetry 无法在托管的 Supabase Edge 上运行。使用上文所述的轻量级 OTel 形态垫片模式;将导出器端点/请求头放在同一个设置区域,并避免使用 Superlog 专属的函数/文件名。
  • **Python/FastAPI:**使用 FastAPIInstrumentor.instrument_app(app) 等原生检测方式,而不是用手动中间件替换请求处理逻辑。
  • **Python/LiveKit:**跨越关闭回调的生命周期跨度可以使用 start_span + trace.use_span(..., end_on_exit=False),并在关闭回调中结束。有界工作仍应使用装饰器或上下文管理器。

与现有可观测性供应商共存。不要移除 Sentry、Datadog、New Relic、Honeycomb、Logtail、Pino 传输器等。 OTel 与它们并行运行。用户明确希望在迁移期间让两种信号都正常流动;是否移除现有方案不由你决定。

第 3 步 — 在业务操作周围添加自定义跨度、指标和日志

自动检测可以捕获 HTTP 请求收发、数据库查询和框架生命周期。这只是基础,并非全部。阅读项目代码,找出当问题出现时,人工运维人员真正希望看到哪些操作。

追踪

为每项关键业务操作添加一个活动跨度。如果已有自动检测跨度,可以直接使用;但如果某项操作还没有跨度,就添加一个。

  • 命名:domain.verb(order.process、payment.charge、email.send、agent.run、interview.create、job.<type>)。

  • 属性:实体 ID(order.id、user.id、workspace.id、tenant.id)、数量、关键布尔分支的结果,以及大模型调用的模型名称/提供方。

  • 记录异常:在失败路径中调用 span.recordException(err) + span.setStatus({ code: ERROR })。

  • 对于边界明确的 Python 函数,优先使用 @tracer.start_as_current_span("operation.name")——同一个调用既可用作装饰器,也可用作上下文管理器;对于整个函数,通常应使用装饰器形式:

    @tracer.start_as_current_span("do_work")
    def do_work():
        print("doing some work...")
    

    装饰器不适用时(例如只需覆盖部分范围、跨度名称是动态的等),请使用上下文管理器。对于有界工作,不要使用独立的 start_span() + 手动 end()。

  • 跳过简单的 getter、纯转换和内部辅助函数——任何没有实际延迟或失败可能性的操作都不必处理。

  • 绝不要在属性中放入个人身份信息(PII)(电子邮件、密码、令牌、完整请求正文)。

日志

确保日志采用结构化格式并携带操作上下文。具体来说:跨度内发出的每一行日志到达 Superlog 时,都应带有已填充的 trace_id / span_id,并将所有结构化字段(orderId、userId 等)保留为属性。追踪/跨度上下文可能由日志桥接器或集成原生添加,也可能需要额外处理。

使用日志记录操作过程(“starting batch reconcile”“retrying after 3xx”)和异常事件。仅当操作无法恢复且需要人工干预时,才应发出错误日志。

指标

覆盖业务、性能和成本。关注以下三个类别:

  • 业务逻辑计数器。 记录每个有意义的状态转换:已创建、已启动、已完成、已失败、已重试。仅使用低基数维度,例如按租户、渠道、状态统计(绝不使用用户 ID/订单 ID)。
  • 性能直方图。 记录用户关心的操作延迟、队列深度、批次大小、负载大小。如果项目已有计时工具(time.perf_counter 代码块、自定义 LatencyTracker 或 "[TIMING]" 日志行),请复用——根据这些测量值生成直方图,而不是重复测量。
  • 成本,尤其是大模型成本。 如果项目调用 OpenAI / Anthropic / Google / 任何大模型提供商,在可用时优先使用 OpenInference 等提供商插桩,以保持原生 SDK 调用的可读性。不要在产品处理程序中添加定价常量或大模型成本计算;Superlog 会在 UI/查询层根据捕获的提供商/模型/令牌属性集中计算预估成本。避免重复统计提供商插桩已捕获的令牌数。

在模块级获取一次 meter,并在模块级创建 instruments,在热路径中递增。不要为每次调用都创建新的 meter。

步骤 4 — 验证应用仍能正常工作

对每个服务:

  1. 运行项目自身的开发或构建命令(即 package.json / pyproject / Makefile 中已有的命令)。确认应用可以正常启动,且没有可追溯到 OTel 安装的问题。同时运行遥测引导冒烟测试来导入或启动应用,以便初始化 provider 设置、exporter 构造、日志桥接和框架插桩。对于 Python 服务,可以运行类似 uv run python -c 'from app.main import app; print(app.title)' 的导入/启动命令;对于 Node/Next,使用仓库的构建/启动流程。对于服务,使用 curl 至少访问一个路由,让流量经过插桩;条件允许时,选择会触发已插桩操作的路由,而不只是静态健康检查路由。对于 CLI,运行一个真实命令。如果应用自身启动因此出现问题,就不要交付——这属于回归。

  2. 通过生产环境发送真实遥测数据,并读取响应码——三个信号都要验证。 这是硬性门槛。驱动运行中的应用,使其实际发出至少一个 span、一条日志和一个指标,然后检查 OTLP exporter 对 /v1/traces、/v1/logs 和 /v1/metrics 的 HTTP 响应。要专门触发日志路径,请访问一个会在已插桩操作内部调用项目 logger 的路由(或运行一个 CLI 命令)。接收端的响应状态就是判断依据:

    • 三者都返回 2xx → 完成。 注册已确认;继续执行步骤 5。不要再引导用户返回注册标签页。
    • 任一返回 401/403 → token 尚未确认。 告诉用户前往步骤 0 中的 URL 完成注册(标签页已经打开)。等待用户确认,然后重新运行冒烟测试并再次检查,直到三者都返回 2xx。401/403 时不要宣布成功。
    • 任一返回 5xx、超时或从未发出 POST → 存在真实问题。 继续调试,解决后再进行下一步。如果只看到 /v1/traces,说明日志桥接未接通(最常见原因:从未设置 LoggerProvider、处理程序挂在了错误的 logger 上、级别筛选过严、缺少 @vercel/otel 的 logRecordProcessor(s),或关闭时未刷新 batch processor)。如果缺少 /v1/metrics,说明 meter provider 或 periodic reader 未接通。

引导程序即使加载成功,但从未发出 POST——或者只发送了 traces,却没有日志/指标——都不算部分成功。继续修复后再进行下一步。

步骤 5 — 交接(给用户的最终消息)

只有在步骤 4 中 /v1/traces、/v1/logs 和 /v1/metrics 都返回 2xx 后,才能进入此步骤。token 已内嵌在引导程序源码中——不要在聊天中把它贴出来。遥测数据正在流入用户的项目;接下来需要部署。

变更内容

3–7 条简短、客观的要点,涵盖:安装的软件包、新建或修改的文件,以及新增的业务跨度/指标。若各服务的变更不同,请按服务分别列出;若变更一致,则合并列出。请说明你有意保留的任何现有可观测性供应商(Sentry、Datadog、Logtail、Pino transports 等),明确它们会继续共存。

部署

现在就引导用户部署;不要只说“按平常方式部署”。根据仓库推断最可能的部署路径,并给出一个具体的下一步操作。

  • 如果仓库有直接部署工具/配置(vercel.json、netlify.toml、fly.toml、wrangler.*、railway.json、render.yaml、Dockerfile、package.json 中的部署脚本等),请指出目标平台,并在运行任何生产/公开部署命令前征求确认:“我可以用 <command> 部署到 <target>。要我运行吗?”如果用户同意,就运行并查看结果。
  • 如果部署由 CI 在推送/合并时触发,请明确说明,并给出用户需要采取的确切下一步:提交/推送/合并分支,或打开现有托管服务控制面板。遵守以下硬性规则:除非用户在技能运行之外明确要求你执行此任务,否则不要通过此技能提交、推送或创建 PR。
  • 如果无法确定生产部署路径,请提供最佳的本地替代方案:启动开发服务器,访问一个已接入监控的路由,并告知用户你使用的确切命令,以及未能找到哪些生产部署信息。
  • 部署或本地运行后,至少访问一个已接入监控的路由,以便部署环境也能产生跟踪、日志和指标。

无需配置 Superlog 环境变量:端点和公开令牌都在引导程序源码中。

步骤 6 — MCP 建议

不要再由 Agent 手动操作 GitHub 或 Slack。用户注册意向页面会在认证后处理这两项集成;如果用户通过 GitHub 登录,页面仍会验证该应用是否拥有正确的仓库权限。

建议安装 Superlog MCP 服务,让 Agent(Claude Code、Codex、Cursor 等)下次调试时能直接查询遥测数据——无需切换到控制面板,就能在聊天中搜索日志、获取跟踪数据、查看错误率。

对于 Claude Code(最常见的情况——当前技能就是在这里运行的),可提出代为运行:

claude mcp add --transport http superlog https://api.superlog.sh/mcp

这会修改用户的 Claude Code 配置。运行前必须征求确认(用户可能使用自定义的 MCP 作用域,或想安装到其他位置)。如果用户拒绝,请输出命令,供他们稍后自行运行。

对于用户可能使用的其他 Agent,可以提及,但不要代为运行:

  • Codex:codex mcp add superlog --url https://api.superlog.sh/mcp && codex mcp login superlog
  • Cursor/其他工具:从 https://superlog.sh/ → Connect 复制 mcpServers 代码段。

最后用一句话引导用户部署应用——他们已经准备好发布了。

硬性规则

  • 绝不要修改项目根目录之外的文件。
  • 绝不要提交、推送或创建 PR。
  • 未先展示确切命令和目标并获得用户明确确认,绝不要运行生产/公开部署命令。
  • 只可内联 sl_public_ 公开数据摄取令牌。绝不要内联账户/会话/管理员令牌、私钥或供应商 API 密钥。不要在聊天中输出完整令牌。
  • 除非用户要求,否则绝不要移除现有可观测性供应商。
  • 使用项目现有的包管理器和日志记录器。
  • 语言支持原生 OTel 软件包时,优先使用;不要重新实现 SDK 已提供的遥测处理逻辑。
  • 如果开发/构建命令因你的监控埋点而报错,这就意味着失败——请修复或报告问题,不要掩盖错误。

评论

支持 Markdown