OpenTelemetry Agent Monitoring

Purpose and Scope

OpenTelemetry monitoring for Copilot Chat is the repository-backed path for observing agent interactions in VS Code. It lets a developer, extension engineer, or administrator see traces, metrics, and events emitted while an agent plans, calls a language model, executes tools, and reports usage. The monitoring documentation describes this as an OpenTelemetry, or OTel, export surface that follows the GenAI semantic conventions, so the same emitted data can flow to common OTel-compatible systems such as local dashboards, Jaeger, Azure Monitor, Datadog, Honeycomb, or Grafana-oriented stacks.

Sources: extensions/copilot/docs/monitoring/agent_monitoring.md, extensions/copilot/src/platform/otel/common/index.ts

The practical goal is not only to turn on a debug log. The feature models agent work as telemetry signals with consistent names and attributes. A single agent request can become a hierarchical trace: an invoke_agent span wraps the orchestration, chat spans represent language model calls, and execute_tool spans represent tool activity. This matters when diagnosing latency, permissions, subagent behavior, token usage, or prompt and response flow, because the trace tree preserves the relationship between agent decisions rather than leaving each event isolated.

Sources: extensions/copilot/docs/monitoring/agent_monitoring.md, extensions/copilot/docs/monitoring/agent_monitoring_arch.md

Relevant Source Files

  • extensions/copilot/docs/monitoring/agent_monitoring.md - user-facing monitoring guide with quick start, settings, environment-variable precedence, exported signal types, and local dashboard instructions.
  • extensions/copilot/docs/monitoring/agent_monitoring_arch.md - developer guide for the Copilot Chat OTel architecture, including foreground agents, Copilot CLI paths, Claude Code integration, bridge behavior, and span hierarchies.
  • extensions/copilot/docs/monitoring/docker-compose.yaml - local monitoring stack that starts an OpenTelemetry Collector and Jaeger with host ports chosen for Copilot Chat testing.
  • extensions/copilot/docs/monitoring/otel-collector-config.yaml - collector pipeline configuration for OTLP receivers, batching, Azure Monitor export, Jaeger export, and debug output.
  • extensions/copilot/src/platform/otel/common/index.ts - common OTel module exports used by Copilot code, including GenAI attributes, events, metrics, configuration resolution, message formatting, workspace metadata, and the IOTelService contract.

Quick Start: Local Trace Viewing

For the shortest local feedback loop, the monitoring guide starts with the Aspire Dashboard standalone container. This path requires Docker and VS Code with the GitHub Copilot Chat extension, but it does not require a cloud account. The container exposes a web UI on port 18888 and an OTLP HTTP endpoint on port 4318. After the dashboard is running, enable Copilot Chat OTel emission in VS Code settings, generate an agent-mode chat request, and inspect the resulting trace in the dashboard.

docker run --rm -d -p 18888:18888 -p 4318:18890 --name aspire-dashboard mcr.microsoft.com/dotnet/aspire-dashboard:latest
{
  "github.copilot.chat.otel.enabled": true,
  "github.copilot.chat.otel.captureContent": true
}

Sources: extensions/copilot/docs/monitoring/agent_monitoring.md

The quick-start sequence is intentionally small: start a receiver, enable emission, send a Copilot Chat request, and view traces. The important setting is github.copilot.chat.otel.enabled, which is disabled by default. github.copilot.chat.otel.captureContent is useful while learning because it includes prompt and response content in telemetry, but it should be treated as a sensitive-data decision. The guide also documents configuration precedence as enterprise policy first, then environment variables, then user or workspace settings, which is important for managed environments where local settings might not be authoritative.

Sources: extensions/copilot/docs/monitoring/agent_monitoring.md

Architecture and Execution Paths

The developer guide explains that Copilot Chat does not have one uniform execution model for all agents. Foreground agent execution runs in the extension host and can create direct IOTelService spans. Copilot CLI can run in-process, where a bridge span processor forwards completed SDK spans into the extension's debug and logging flow. Copilot CLI can also run as a separate terminal process, where the extension forwards OTel environment variables instead of directly owning the spans. Claude Code runs as a child process, so the extension synthesizes spans from SDK messages and proxies model calls through the language model path.

Sources: extensions/copilot/docs/monitoring/agent_monitoring_arch.md

This asymmetry is a design constraint for anyone reading trace data. A foreground trace and an in-process Copilot CLI trace can both show a rich tree, but they are produced differently. The bridge path depends on internal OpenTelemetry SDK provider structures because the public span-processor API changed in OTel SDK v2; the documentation explicitly calls out a runtime guard and graceful degradation for that fragile access. Claude traces are different again: internal child-process spans are not directly visible, so the extension translates observable messages into GenAI-shaped spans.

Sources: extensions/copilot/docs/monitoring/agent_monitoring_arch.md

The architecture guide's span examples define the mental model for reading the data. Foreground and inline chat flows start with an invoke_agent span, include one or more chat spans for model requests, and nest tool execution under the relevant turn. In-process Copilot CLI traces can include subagent invocation beneath an execute_tool span, preserving trace context across asynchronous agent boundaries. A terminal Copilot CLI run is independent and identifies itself with a service name from the standalone process, so dashboards should not assume every span originated in the extension host.

Sources: extensions/copilot/docs/monitoring/agent_monitoring_arch.md

Collector and Docker Compose Stack

The repository includes a Docker Compose stack for a fuller local or development monitoring environment. It starts otel/opentelemetry-collector-contrib:latest with the repository collector configuration mounted read-only, accepts OTLP gRPC on host port 4327, accepts OTLP HTTP on host port 4328, and starts jaegertracing/jaeger:latest with the Jaeger UI exposed on host port 16687. The compose file also passes APPLICATIONINSIGHTS_CONNECTION_STRING into the collector so the same stack can forward to Azure Application Insights when configured.

export APPLICATIONINSIGHTS_CONNECTION_STRING="InstrumentationKey=...;IngestionEndpoint=..."
docker compose -f extensions/copilot/docs/monitoring/docker-compose.yaml up -d
COPILOT_OTEL_ENABLED=true OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4328 code .

Sources: extensions/copilot/docs/monitoring/docker-compose.yaml

The collector configuration receives OTLP over both HTTP and gRPC on container ports 4318 and 4317, batches telemetry with a five-second timeout and batch size of 256, and defines three exporters. The azuremonitor exporter uses the connection string environment variable, the debug exporter prints basic output to collector stdout, and otlphttp/jaeger forwards traces to Jaeger at http://jaeger:4318. The service section wires traces to Azure Monitor, Jaeger, and debug, while metrics and logs go to Azure Monitor and debug.

Sources: extensions/copilot/docs/monitoring/otel-collector-config.yaml

Configuration and API Components

The monitoring guide exposes configuration through VS Code settings and environment variables. The visible settings include github.copilot.chat.otel.enabled, github.copilot.chat.otel.exporterType, github.copilot.chat.otel.otlpEndpoint, github.copilot.chat.otel.captureContent, github.copilot.chat.otel.protocol, github.copilot.chat.otel.serviceName, github.copilot.chat.otel.resourceAttributes, github.copilot.chat.otel.headers, github.copilot.chat.otel.maxAttributeSizeChars, github.copilot.chat.otel.outfile, and github.copilot.chat.otel.dbSpanExporter.enabled. The exporter type can target OTLP over HTTP, OTLP over gRPC, console, or file output, making the same instrumentation useful for both local diagnosis and backend ingestion.

Sources: extensions/copilot/docs/monitoring/agent_monitoring.md

ComponentRepository contractWhy it matters
IOTelServiceExported from extensions/copilot/src/platform/otel/common/index.tsCommon service contract for creating and completing spans in Copilot code.
resolveOTelConfig and DEFAULT_OTLP_ENDPOINTExported from the common OTel indexCentralizes configuration resolution and the default endpoint used by the extension.
GenAiMetricsExported from the common OTel indexProvides the metrics surface alongside traces and events.
emitToolCallEvent, emitSessionStartEvent, and related event functionsExported from the common OTel indexDefines named event emitters for agent turns, tool calls, edit feedback, inference details, and user feedback.
truncateForOTel and message formatter exportsExported from the common OTel indexFormats prompts, responses, tools, and system instructions for telemetry while supporting size controls.

Sources: extensions/copilot/src/platform/otel/common/index.ts

The common OTel index is the source-level entry point for the rest of the Copilot extension. It re-exports attribute constants such as GenAiAttr, GitHubCopilotAttr, and CopilotChatAttr, event helpers such as emitAgentTurnEvent and emitToolCallEvent, metrics via GenAiMetrics, formatting helpers for messages and tool definitions, and the IOTelService types for spans and trace context. That barrel export shows that monitoring is not a single dashboard feature; it is a shared platform layer used by agent execution, message processing, configuration, and workspace metadata.

Sources: extensions/copilot/src/platform/otel/common/index.ts

Emitted Telemetry Surfaces and Reading Traces

Copilot Chat emits traces, metrics, and events, and the documentation emphasizes three attribute namespaces. gen_ai.* is used where the OpenTelemetry GenAI semantic conventions define a standard key. github.copilot.* is the canonical Copilot-specific namespace shared with GitHub Copilot CLI conventions and is the preferred namespace for new dashboards and alerts. copilot_chat.* is the original VS Code extension namespace and remains emitted for compatibility, with some values dual-emitted alongside newer keys. Dashboards should therefore prefer the GitHub namespace while tolerating legacy attributes.

Sources: extensions/copilot/docs/monitoring/agent_monitoring.md, extensions/copilot/src/platform/otel/common/index.ts

When investigating a slow or surprising agent response, start at the outer invoke_agent span and move inward. The total duration identifies orchestration cost. Child chat spans show model-call timing, model identity, and token-related information when available. execute_tool spans expose tool latency and can reveal whether the agent spent time reading files, running shell commands, applying patches, or waiting for permissions. If subagents are involved, a nested invoke_agent span under a tool execution indicates propagated trace context rather than a separate unrelated session.

Sources: extensions/copilot/docs/monitoring/agent_monitoring.md, extensions/copilot/docs/monitoring/agent_monitoring_arch.md

Operational Guidance and Next Steps

For local development, use the Aspire quick start when you want immediate visual confirmation that spans are being emitted, and use the Docker Compose stack when you need a collector pipeline that resembles production-style routing. For enterprise or team environments, check policy-controlled settings before assuming local configuration will take effect, and be deliberate about content capture because prompts, tool arguments, tool results, and model responses can contain source code or secrets. For backend compatibility, keep queries aligned with GenAI semantic conventions and prefer github.copilot.* attributes for new work.

Sources: extensions/copilot/docs/monitoring/agent_monitoring.md, extensions/copilot/docs/monitoring/docker-compose.yaml, extensions/copilot/docs/monitoring/otel-collector-config.yaml

Next, read the Copilot and AI overview to understand the agent surfaces that produce these spans, the chat tools and approvals page to interpret tool-related telemetry, and the AI troubleshooting page for log- and test-oriented diagnostics. If you are changing implementation code, begin with the OTel common exports and the architecture guide before modifying a specific execution path, because foreground agents, Copilot CLI, terminal processes, and Claude Code have different trace-production strategies and different failure modes.

Sources: extensions/copilot/docs/monitoring/agent_monitoring_arch.md, extensions/copilot/src/platform/otel/common/index.ts