
Copilot SDK 观测性指南OpenTelemetry 插桩与 trace 上下文传播【免费下载链接】copilot-sdkMulti-platform SDK for integrating GitHub Copilot Agent into apps and services项目地址: https://gitcode.com/GitHub_Trending/co/copilot-sdk本文是 GitHub Copilot SDK 观测性Observability主题的完整技术指南以 docs/observability/README.md 为核心骨架系统讲解如何为基于 Copilot SDK 构建的应用接入 OpenTelemetry 追踪从TelemetryConfig一行配置接入到 W3C Trace Context 在 SDK 与 CLI 之间的双向传播再到结合assistant.usage事件做端点级成本归因。阅读完成后你将能在 Node.js、Python、Go、.NET、Java、Rust 任一语言中启用 CLI 进程的 OpenTelemetry 导出并让你的应用 span 与 CLI span 落在同一条分布式链路中。观测性概览SDK 能观测到什么Copilot SDK 把应用你的进程与 Copilot CLI/运行时子进程或进程内运行时连接起来。这一架构天然产生两类可观测信号追踪TracesCLI 内部执行会话创建、工具调用、模型请求时产生的大量 span。SDK 提供内置的TelemetryConfig可在启动 CLI 时为其配置 OpenTelemetryOTLP导出并支持 W3C Trace Context 在你的应用与 CLI 之间双向传播。事件Session eventsSDK 通过 session 事件流把 agent 的每个动作思考、写代码、运行工具实时推给应用其中assistant.usage事件携带 token 用量与apiEndpoint字段用于成本归因和端点级分析。核心文档 docs/observability/README.md 给出了这一主题的入口本指南将逐层展开。内置遥测支持用 TelemetryConfig 一行开启SDK 内置了对 OpenTelemetry 的支持在创建 client 时提供一个TelemetryConfig即可opt in。其工作机制是SDK 把配置翻译为对应环境变量设置到其启动的 CLI 子进程环境中CLI 进程内置的 OTel exporter 会自动据此完成初始化无需你改动 CLI 或 agent 本身的任何代码。这一点可以从各语言实现中得到印证例如 Python 端在 python/copilot/client.py#L4422-L4439 中当telemetry配置存在时会先写入COPILOT_OTEL_ENABLEDtrue随后把otlp_endpoint、otlp_protocol、file_path、exporter_type、source_name、capture_content逐一映射为OTEL_EXPORTER_OTLP_ENDPOINT、OTEL_EXPORTER_OTLP_PROTOCOL、COPILOT_OTEL_FILE_EXPORTER_PATH、COPILOT_OTEL_EXPORTER_TYPE、COPILOT_OTEL_SOURCE_NAME、OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT等环境变量Go 端在 go/client.go#L2145-L2155 使用setEnvValue完成同样的注入.NET 端在 dotnet/src/Client.cs#L2250-L2261 的ApplyTelemetryEnvironment中做映射。也就是说TelemetryConfig本质上是一个环境变量装配层它让你用类型安全的结构体代替手写环境变量。以下是六种语言的启用示例均来自 docs/observability/opentelemetry.mdimport { CopilotClient } from github/copilot-sdk; const client new CopilotClient({ telemetry: { otlpEndpoint: http://localhost:4318, }, });from copilot import CopilotClient client CopilotClient( telemetry{ otlp_endpoint: http://localhost:4318, }, )client : copilot.NewClient(copilot.ClientOptions{ Telemetry: copilot.TelemetryConfig{ OTLPEndpoint: http://localhost:4318, }, })var client new CopilotClient(new CopilotClientOptions { Telemetry new TelemetryConfig { OtlpEndpoint http://localhost:4318, }, });import com.github.copilot.CopilotClient; import com.github.copilot.rpc.*; var client new CopilotClient(new CopilotClientOptions() .setTelemetry(new TelemetryConfig() .setOtlpEndpoint(http://localhost:4318)) );use github_copilot_sdk::{Client, ClientOptions, TelemetryConfig}; let client Client::start(ClientOptions::new() .with_telemetry(TelemetryConfig::new() .with_otlp_endpoint(http://localhost:4318)) ).await?;http://localhost:4318是 OTLP HTTP 的默认端口约定4317 为 gRPC如果你在本机跑一个 OTel Collector如otel-collector-contrib将其暴露的 HTTP 接收端口指向即可。TelemetryConfig 全部选项各语言字段命名遵循各自的命名约定语义完全一致。下表为 docs/observability/opentelemetry.md 中的完整选项对照OptionNode.jsPythonGo.NETJavaRustDescriptionOTLP endpointotlpEndpointotlp_endpointOTLPEndpointOtlpEndpointotlpEndpointotlp_endpointOTLP HTTP endpoint URLOTLP protocolotlpProtocolotlp_protocolOTLPProtocolOtlpProtocolotlpProtocolotlp_protocolOTLP HTTP protocol for all signals:http/jsonorhttp/protobufFile pathfilePathfile_pathFilePathFilePathfilePathfile_pathFile path for JSON-lines trace outputExporter typeexporterTypeexporter_typeExporterTypeExporterTypeexporterTypeexporter_typeotlp-httporfileSource namesourceNamesource_nameSourceNameSourceNamesourceNamesource_nameInstrumentation scope nameCapture contentcaptureContentcapture_contentCaptureContentCaptureContentcaptureContentcapture_contentWhether to capture message content从源码看每个选项都精确对应一个环境变量这是理解其行为的关键otlpEndpoint→OTEL_EXPORTER_OTLP_ENDPOINTOTLP HTTP 导出地址通常指向你的 Collector 或后端见 nodejs/src/types.ts#L132-L145。otlpProtocol→OTEL_EXPORTER_OTLP_PROTOCOL控制 CLI 的otlp-httpexporter 在所有信号上使用的传输格式。不设置则使用 CLI 默认值设置为http/protobuf则以 protobuf 二进制编码经 HTTP 导出更紧凑、吞吐更高http/json则是人类可读的 JSON 编码。filePath→COPILOT_OTEL_FILE_EXPORTER_PATHJSON-linesNDJSONtrace 输出文件路径每行一条 span 记录适合本地调试或离线采集。exporterType→COPILOT_OTEL_EXPORTER_TYPE导出后端类型otlp-http或file。注意它是 CLI 侧的导出后端开关与 OTLP 协议配置配合使用。sourceName→COPILOT_OTEL_SOURCE_NAMEInstrumentation scope仪表化作用域名称在 UI 中用于区分 span 来源。captureContent→OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT是否采集消息内容prompt、response。涉及敏感业务数据生产环境需谨慎评估。提示Python 的TelemetryConfig定义在 python/copilot/client.py#L492-L509Go 的定义在 go/types.go#L274-L299.NET 的定义在 dotnet/src/Types.cs#L494-L538各字段注释均标注了对应的环境变量可作为字段语义的权威参考。Trace 上下文传播应用与 CLI 共享一条分布式链路对于绝大多数用户上文的TelemetryConfig已足够采集 CLI 的 traces。文档明确强调trace 上下文传播是高级特性适用于那些应用自己创建 OpenTelemetry span、并希望与 CLI span 处于同一条分布式 trace中的场景——例如你想在应用侧看到handle tool call span 嵌套在 CLI 的execute tool span 之内或把 SDK 调用显示为你请求处理 span 的子 span。其实现载体是 W3C Trace Context 标准头traceparent/tracestateSDK 把这些字段携带在 JSON-RPC 负载上在应用与 CLI 之间传递。传播分两个方向SDK → CLI出站Node.js由于 SDK 不依赖任何 OpenTelemetry 包需要你在 client options 上提供onGetTraceContext回调。SDK 会在session.create、session.resume、session.send这些 RPC 发出之前调用它取得当前 active context 并注入到 JSON-RPC 负载中import { CopilotClient } from github/copilot-sdk; import { propagation, context } from opentelemetry/api; const client new CopilotClient({ telemetry: { otlpEndpoint: http://localhost:4318 }, onGetTraceContext: () { const carrier: Recordstring, string {}; propagation.inject(context.active(), carrier); return carrier; // { traceparent: 00-..., tracestate: ... } }, });这与 nodejs/src/telemetry.ts#L20-L27 的实现一致getTraceContext调用用户提供的 provider未配置时返回空对象provider 抛错时也安全降级为空对象。Python、Go、.NETtrace 上下文注入是自动的——只要你的应用配置了对应的 OpenTelemetry/Activity APISDK 会在出站 RPC 时自动注入无需回调。CLI → SDK入站当 CLI 调用你注册的工具 handler 时CLI span 的traceparent与tracestate会随调用传入各语言处理方式不同GoToolInvocation.TraceContext字段是一个已恢复好 trace 的context.Context直接作为你 span 的 parent 使用即可。Pythonhandler 执行期间通过trace_context()自动恢复上下文子 span 自动挂在 CLI span 下。.NET通过RestoreTraceContext()自动恢复子Activity实例自动以 CLI span 为 parent。Node.jsSDK 无 OpenTelemetry 依赖traceparent与tracestate以原始字符串形式出现在ToolInvocation对象上需要你手动恢复。官方示例import { defineTool } from github/copilot-sdk; import { propagation, context, trace } from opentelemetry/api; const myTool defineTool(my-tool, { description: Do work, handler: async (args, invocation) { // Restore the CLIs trace context as the active context const carrier { traceparent: invocation.traceparent, tracestate: invocation.tracestate, }; const parentCtx propagation.extract(context.active(), carrier); // Create a child span under the CLIs span const tracer trace.getTracer(my-app); return context.with(parentCtx, () tracer.startActiveSpan(my-tool, async (span) { try { const result await doWork(args); return result; } finally { span.end(); } }) ); }, }); // Tool handlers are registered when the session is created. const session await client.createSession({ tools: [myTool] });关键点在于propagation.extract把 CLI 的 traceparent 还原为 parent contextcontext.with使其成为 active随后startActiveSpan创建的 span 便自动成为 CLI span 的子 span——整个调用链CLI 的execute tool span → 你的my-tool span在同一条分布式 trace 中即可视化。各语言依赖速查LanguageDependencyNotesNode.js—无依赖出站传播通过onGetTraceContext回调实现Pythonopentelemetry-api安装方式pip install copilot-sdk[telemetry]Gogo.opentelemetry.io/otel必需依赖.NET—使用内置的System.Diagnostics.ActivityJavaio.opentelemetry:opentelemetry-api配置 OpenTelemetry Java agent 或 SDK 后trace 上下文注入自动生效注意Rust 未列入依赖表该语言目前以服务端/CLI 使用为主Node.js 则因为刻意保持零 OpenTelemetry 依赖出站传播需要回调而入站恢复需要手动是唯一需要你写胶水代码的语言。成本归因用 assistant.usage 事件做端点级分析追踪回答了发生了什么而花了多少则需要事件流。SDK 的每个动作都会以 session event 形式发出订阅assistant.usage事件可以拿到单次模型 API 调用的 token 用量与成本信息其数据字段包括完整字段见 docs/features/streaming-events.md#assistantusage字段说明model模型标识如gpt-5.4inputTokens/outputTokens输入 / 输出 token 数reasoningTokens用于思考/链式推理的输出 tokenoutputTokens的子集cacheReadTokens/cacheWriteTokensprompt 缓存读写 tokencost模型倍率成本用于计费duration/timeToFirstTokenMs/interTokenLatencyMs调用耗时、首 token 延迟、token 间平均延迟apiEndpoint端点标识/chat/completions、/v1/messages、/responses或ws:/responsesResponses API 的 websocket 变体providerCallId/serviceRequestId供应商 completion ID 与 Copilot 服务请求 IDx-copilot-service-request-id用于 CAPI 日志关联contentFilterTriggered/finishReason内容过滤是否触发、模型结束原因其中apiEndpoint字段类型名AssistantUsageApiEndpoint正是文档推荐用于端点级成本归因的关键通过它你可以判断一次对话轮次走的是 Chat Completions、Responses 还是 Anthropic Messages 接口从而按 API 端点维度聚合成本与延迟。提示assistant.usage是 ephemeral临时事件不会被写入 session 事件日志、也不会在会话恢复时重放因此必须在事件实时流中处理例如在session.on(...)订阅里聚合而不要指望事后从getMessages恢复。结合源码的观测架构小结把以上内容串起来Copilot SDK 的观测架构可以概括为三层配置层TelemetryConfig通过环境变量装配OTEL_EXPORTER_OTLP_*、COPILOT_OTEL_*为 CLI 进程启用内置 OTel exporter——见 go/client.go#L2145-L2155、python/copilot/client.py#L4422-L4439、dotnet/src/Client.cs#L2250-L2261。链路层W3C Trace Context 沿 JSON-RPC 双向传播SDK→CLI 出站注入、CLI→SDK 入站恢复把应用 span 与 CLI span 连接为同一分布式 traceNode.js 侧的无依赖设计由 nodejs/src/telemetry.ts 的getTraceContext实现佐证。事件层session 事件流尤其assistant.usage的apiEndpoint补充端点级成本、延迟与 token 归因见 docs/features/streaming-events.md。相关测试与示例也印证了上述行为Go 端在 go/internal/e2e/client_options_e2e_test.go#L112-L154 中验证了TelemetryConfig各项设置会映射为预期的环境变量并在 go/internal/e2e/telemetry_e2e_test.go 覆盖了配置形状与默认值Node.js 端 telemetry 单测位于 nodejs/test/telemetry.test.ts。如果你要在本机验证只需把otlpEndpoint指向本地 Collector 或 OTel 后端即可在 Jaeger、Tempo 等 UI 中观察到 CLI 与工具调用的完整 span 瀑布。快速上手三步① 创建 client 时传入telemetry: { otlpEndpoint: ... }② 若需应用与 CLI 链路互通按语言配置 trace 上下文传播Node.js 用onGetTraceContext回调 工具 handler 内手动恢复③ 在session.on中订阅assistant.usage并按apiEndpoint聚合成本。【免费下载链接】copilot-sdkMulti-platform SDK for integrating GitHub Copilot Agent into apps and services项目地址: https://gitcode.com/GitHub_Trending/co/copilot-sdk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考