# Инструментация OpenTelemetry для Copilot SDK

В этом руководстве показано, как добавить трассировку OpenTelemetry в ваши приложения Copilot SDK.

<!-- markdownlint-disable GHD046 GHD005 -->

<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->

## Встроенная поддержка телеметрии

SDK поддерживает встроенную поддержку настройки OpenTelemetry на процессе CLI и распространения W3C Trace Context между SDK и CLI. Указывайте `TelemetryConfig` при создании клиента для регистрации:

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

<!-- docs-validate: skip -->

```typescript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient({
  telemetry: {
    otlpEndpoint: "http://localhost:4318",
  },
});
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

<!-- docs-validate: skip -->

```python
from copilot import CopilotClient

client = CopilotClient(
    telemetry={
        "otlp_endpoint": "http://localhost:4318",
    },
)
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

<!-- docs-validate: skip -->

```golang
client := copilot.NewClient(&copilot.ClientOptions{
    Telemetry: &copilot.TelemetryConfig{
        OTLPEndpoint: "http://localhost:4318",
    },
})
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

<!-- docs-validate: skip -->

```csharp
var client = new CopilotClient(new CopilotClientOptions
{
    Telemetry = new TelemetryConfig
    {
        OtlpEndpoint = "http://localhost:4318",
    },
});
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

<!-- docs-validate: skip -->

```java
import com.github.copilot.CopilotClient;
import com.github.copilot.rpc.*;

var client = new CopilotClient(new CopilotClientOptions()
    .setTelemetry(new TelemetryConfig()
        .setOtlpEndpoint("http://localhost:4318"))
);
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

<!-- docs-validate: skip -->

```rust
use github_copilot_sdk::{Client, ClientOptions, TelemetryConfig};

let client = Client::start(ClientOptions::new()
    .with_telemetry(TelemetryConfig::new()
        .with_otlp_endpoint("http://localhost:4318"))
).await?;
```

</div>

</div>

### Опции TelemetryConfig

| Опция                      | Node.js          | Python            | Go               | .NET             | Java             | Rust              | Описание                                                                  |
| -------------------------- | ---------------- | ----------------- | ---------------- | ---------------- | ---------------- | ----------------- | ------------------------------------------------------------------------- |
| Конечная точка OTLP        | `otlpEndpoint`   | `otlp_endpoint`   | `OTLPEndpoint`   | `OtlpEndpoint`   | `otlpEndpoint`   | `otlp_endpoint`   | URL конечной точки OTLP HTTP                                              |
| Протокол OTLP              | `otlpProtocol`   | `otlp_protocol`   | `OTLPProtocol`   | `OtlpProtocol`   | `otlpProtocol`   | `otlp_protocol`   | Протокол OTLP HTTP для всех сигналов: `"http/json"` или `"http/protobuf"` |
| Путь к файлу               | `filePath`       | `file_path`       | `FilePath`       | `FilePath`       | `filePath`       | `file_path`       | Путь файла для вывода JSON-lines trace                                    |
| Тип экспортера             | `exporterType`   | `exporter_type`   | `ExporterType`   | `ExporterType`   | `exporterType`   | `exporter_type`   |                                                                           |
| `"otlp-http"` или `"file"` |                  |                   |                  |                  |                  |                   |                                                                           |
| Имя источника              | `sourceName`     | `source_name`     | `SourceName`     | `SourceName`     | `sourceName`     | `source_name`     | Название области приборов                                                 |
| Захват контента            | `captureContent` | `capture_content` | `CaptureContent` | `CaptureContent` | `captureContent` | `capture_content` | Нужно ли фиксировать содержимое сообщений                                 |

Поле протокола OTLP настраивает `"otlp-http"` экспортера CLI для всех сигналов. Оставьте его неустановленным, чтобы использовать CLI по умолчанию, или поставьте на `"http/protobuf"` экспорт protobuf через HTTP.

### Распространение контекста следов

> **Большинству пользователей это не нужно.** Вышеописанное — всё, `TelemetryConfig` что нужно для сбора трассировок из CLI. Распространение контекста трассировки, описанное в этом разделе, является **продвинутой функцией** для приложений, которые создают собственные OpenTelemetry spans и хотят, чтобы они отображались **в той же распределённой трассе** , что и spans CLI.

SDK может передавать W3C Trace Context (`traceparent`/`tracestate`) на JSON-RPC полезных нагрузках, чтобы span-и вашего приложения и CLI были связаны в одну распределённую трассу. Это полезно, когда, например, вы хотите увидеть span «handle tool call» в вашем приложении, встроенный в span «execute tool» CLI, или показывать SDK-вызов как дочерний span обработки запросов.

Для атрибуции стоимости вместе с трассами подписывайтесь на события `assistant.usage` и проверяйте `apiEndpoint` (`AssistantUsageApiEndpoint`), чтобы узнать, использовал ли ход завершения чата, ответы или Anthropic сообщения; см. [События потоковых сессий](/ru/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/streaming-events).

#### SDK → CLI (исходящий маршрут)

Для **Node.js**дайте обратный `onGetTraceContext` звонок по вариантам клиента. Это необходимо только если ваше приложение уже использует `@opentelemetry/api` это и вы хотите связать свои соны с спанами CLI. SDK вызывает этот обратный вызов перед `session.create`, `session.resume`, и `session.send` RPC:

<!-- docs-validate: skip -->

```typescript
import { CopilotClient } from "@github/copilot-sdk";
import { propagation, context } from "@opentelemetry/api";

const client = new CopilotClient({
  telemetry: { otlpEndpoint: "http://localhost:4318" },
  onGetTraceContext: () => {
    const carrier: Record<string, string> = {};
    propagation.inject(context.active(), carrier);
    return carrier; // { traceparent: "00-...", tracestate: "..." }
  },
});
```

Для **Python**, **Go** и **.NET** инъекция контекста trace происходит автоматически при настройке соответствующего API OpenTelemetry/Activity — обратный вызов не требуется.

#### CLI → SDK (входящий)

Когда CLI вызывает обработчик инструментов, `traceparent` диапазон и `tracestate` из CLI доступны во всех языках:

* **Вперед**: поле `ToolInvocation.TraceContext` уже `context.Context` восстановлено с трассировкой — используйте его напрямую как родителя для ваших пролётов.
* **Python**: Контекст трассировки автоматически восстанавливается вокруг обработчика через `trace_context()` — дочерние спыны автоматически прикрепляются к спану CLI.
* **.NET**: Трассирующий контекст автоматически восстанавливается через `RestoreTraceContext()` — дочерние экземпляры `Activity` автоматически связываются с span CLI.
* **Node.js**: Поскольку SDK не зависит `traceparent` от OpenTelemetry и `tracestate` передаются в виде сырых строк на объекте `ToolInvocation` . При необходимости восстанавливайте контекст вручную:

<!-- docs-validate: skip -->

```typescript
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 CLI's 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 CLI's 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] });
```

### Зависимости по языкам

| Язык    | Зависимость                          | Notes                                                                                                                                                   |
| ------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Node.js | —                                    | Никакой зависимости; обеспечить `onGetTraceContext` обратный вызов для исходящего распространения                                                       |
| Python  | `opentelemetry-api`                  | Установка с помощью `pip install copilot-sdk[telemetry]`                                                                                                |
| Go      | `go.opentelemetry.io/otel`           | Требуемая зависимость                                                                                                                                   |
| .NET    | —                                    | Использование встроенных систем `System.Diagnostics.Activity`                                                                                           |
| Java    | `io.opentelemetry:opentelemetry-api` | Добавьте эту зависимость для настройки на основе SDK; инъекция контекста trace происходит автоматически при настройке агента OpenTelemetry Java или SDK |

## Ссылки

* [Семантические конвенции OpenTelemetry GenAI](https://opentelemetry.io/docs/specs/semconv/gen-ai/)
* [Семантические конвенции MCP OpenTelemetry](https://opentelemetry.io/docs/specs/semconv/gen-ai/mcp/)
* [Пакет SDK Python OpenTelemetry](https://opentelemetry.io/docs/instrumentation/python/)
* [Copilot документация SDK](https://github.com/github/copilot-sdk)