Skip to main content
Skip to content

OpenTelemetry reference

Find configuration options and telemetry data to monitor Copilot agent activity across clients.

OpenTelemetry monitoring

The Copilot runtime can export traces and metrics via OpenTelemetry (OTel), giving you visibility into agent interactions, LLM calls, tool executions, and token usage. GenAI signal names and attributes follow the OTel GenAI Semantic Conventions. The runtime also emits Copilot-specific signals under the github.copilot.* namespace.

The configuration and telemetry tables in this article describe the shared Copilot runtime used by these clients and harnesses:

  • Copilot CLI
  • The GitHub Copilot app
  • VS Code Copilot sessions using Agent Host

VS Code's Local agent harness has different environment variables, defaults, and telemetry signals. For example, it uses COPILOT_OTEL_CAPTURE_CONTENT for content capture, defaults service.name to copilot-chat, and emits events such as copilot_chat.session.start. The tables below do not describe that harness or extension-emitted telemetry. See Monitor agent usage with OpenTelemetry in the VS Code documentation.

OTel configuration can also be set in VS Code, or in an enterprise-wide managed-settings.json file. See Enable OTel monitoring in the VS Code documentation and Unternehmensverwaltete Einstellungen.

OTel environment variables

VariableDefaultDescription
COPILOT_OTEL_ENABLEDfalseExplicitly enable OTel. Not required if OTEL_EXPORTER_OTLP_ENDPOINT is set.
OTEL_EXPORTER_OTLP_ENDPOINT—OTLP endpoint URL. Setting this automatically enables OTel.
COPILOT_OTEL_EXPORTER_TYPEotlp-httpExporter type: otlp-http or file. Auto-selects file when COPILOT_OTEL_FILE_EXPORTER_PATH is set.
OTEL_EXPORTER_OTLP_PROTOCOLhttp/jsonOTLP HTTP wire protocol: http/json or http/protobuf. Only applies to the otlp-http exporter.
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL—Override OTEL_EXPORTER_OTLP_PROTOCOL for traces only.
OTEL_EXPORTER_OTLP_METRICS_PROTOCOL—Override OTEL_EXPORTER_OTLP_PROTOCOL for metrics only.
OTEL_SERVICE_NAMEgithub-copilotService name in resource attributes.
OTEL_RESOURCE_ATTRIBUTES—Extra resource attributes as comma-separated key=value pairs. Use percent-encoding for special characters.
OTEL_INSTRUMENTATION_GENAI_CAPTURE_CONTENTNO_CONTENTCapture full prompt and response content. Accepts NO_CONTENT, SPAN_ONLY, SPAN_AND_EVENT, or EVENT_ONLY. See Content capture.
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENTfalseLegacy boolean fallback, used only when the standard content variable is empty or unset. See Content capture.
OTEL_LOG_LEVEL—OTel diagnostic log level: NONE, ERROR, WARN, INFO, DEBUG, VERBOSE, ALL.
COPILOT_OTEL_FILE_EXPORTER_PATH—Write all signals to this file as JSON-lines. Setting this automatically enables OTel.
COPILOT_OTEL_SOURCE_NAMEgithub.copilotInstrumentation scope name for tracer and meter.
OTEL_EXPORTER_OTLP_HEADERS—Authentication headers for the OTLP exporter, as comma-separated key=value pairs.

Transport security

These variables apply only to the otlp-http exporter with an https:// endpoint, and only once OTel export is enabled. They do not enable OTel on their own, and they have no effect on the file exporter.

VariableDescription
OTEL_EXPORTER_OTLP_CERTIFICATEPath to a PEM file with extra CA certificates to trust for the OTLP endpoint, such as a private or corporate CA. Merged with the operating system trust store, so public-CA endpoints still validate.
OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATEPath to the client certificate PEM for mutual TLS (mTLS).
OTEL_EXPORTER_OTLP_CLIENT_KEYPath to the matching unencrypted private key PEM. Both certificate and key must be set together, and passphrase-protected keys are not supported.

Per-signal variants override the generic variables for a single signal: OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE, OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE, and the matching _CLIENT_CERTIFICATE and _CLIENT_KEY names.

Warnung

If the otlp-http exporter resolves to an http:// endpoint, including the default http://localhost:4318, export is disabled rather than sent in cleartext. Startup is not aborted and nothing is reported on the console—the only signal is a warning in the process log. NODE_EXTRA_CA_CERTS does not affect the OTLP exporter, which uses a native HTTP transport, so use the variables above instead.

Dynamic authentication headers

In Copilot CLI, set telemetry.headersProvider in your user settings or in an enterprise-managed telemetry policy to run a command that supplies fresh OTLP headers. Repository settings never apply this setting.

{
  "telemetry": {
    "headersProvider": {
      "path": "node",
      "args": ["bin/otel-headers.js"],
      "refreshIntervalMs": 1740000
    }
  }
}
FieldDescription
pathExecutable name, absolute path, or home-relative path. This is not a shell command, and workspace-relative paths are rejected.
argsOptional arguments, passed literally. Select an interpreter explicitly for scripts (for example, node).
refreshIntervalMsOptional refresh interval. Default: 29 minutes.

Set headersProvider to false to disable dynamic headers.

  • The command runs from your home directory with a 30-second deadline. Its stdout must be a JSON object of string header values. An empty object clears dynamic headers.
  • The provider runs only for active HTTP OTLP exporters. Use HTTPS, because an HTTP endpoint produces a warning and OTLP redirects are rejected.
  • Header precedence, from highest to lowest: managed helper output, managed static headers, user helper output, then OTEL_EXPORTER_OTLP_HEADERS. A managed helper overrides a user helper, and a managed false disables helpers.
  • If a refresh fails, exports that need dynamic headers are blocked until the next refresh.

Traces

The runtime emits a hierarchical span tree for each agent interaction. Each tree contains an invoke_agent root span, with chat and execute_tool child spans. In plan mode, an intermediate plan span wraps the task-decomposition work and parents its own chat and execute_tool spans. chat spans are named chat {model}, falling back to chat when the model is unavailable. Subagent invocations are linked into the same trace by context propagation.

invoke_agent span attributes

Wraps the entire agent invocation: all LLM calls and tool executions for one user message.

  • Both top-level sessions and subagent invocations (for example, explore, task) use span kind INTERNAL (in-process); provider-facing inference is represented by child CLIENT chat spans.
  • Top-level sessions additionally carry server.address and server.port; subagent invocations do not.
AttributeDescriptionScope
gen_ai.operation.nameinvoke_agentBoth
gen_ai.provider.nameProvider (for example, github, anthropic)Both
gen_ai.agent.idStable agent-definition identifier when known; top-level default uses github.copilot.defaultBoth
gen_ai.agent.nameAgent name (when available)Both
gen_ai.agent.descriptionAgent description (when available)Both
gen_ai.agent.versionAgent definition version when known; otherwise runtime versionBoth
gen_ai.conversation.idSession identifierBoth
enduser.pseudo.idPseudonymous Copilot user identifier from analytics_tracking_id when availableBoth
gen_ai.request.modelRequested modelBoth
gen_ai.response.finish_reasons["stop"] or ["error"]Both
gen_ai.usage.input_tokensTotal input tokens (all turns)Both
gen_ai.usage.output_tokensTotal output tokens (all turns)Both
gen_ai.usage.cache_read.input_tokensCached input tokens readBoth
gen_ai.usage.cache_write.input_tokensCached input tokens writtenBoth
gen_ai.usage.reasoning.output_tokensReasoning output tokensBoth
github.copilot.turn_countNumber of LLM round-tripsBoth
github.copilot.costPer-request model multiplier used for billing. Not a monetary value.Both
github.copilot.nano_aiuAI units consumed, in nano AI units (1 AIU = 1,000,000,000 nano AIU)Both
server.addressServer hostnameTop-level only
server.portServer portTop-level only
error.typeError class name (on error)Both
gen_ai.input.messagesFull input messages as JSON (content capture only)Both
gen_ai.output.messagesFull output messages as JSON (content capture only)Both
gen_ai.system_instructionsSystem prompt content as JSON (content capture only)Both
gen_ai.tool.definitionsTool schemas as JSON (content capture only)Both

chat span attributes

One span per LLM request. Span kind: CLIENT.

AttributeDescription
gen_ai.operation.namechat
gen_ai.provider.nameProvider name
gen_ai.request.modelRequested model
gen_ai.request.streamWhether streaming mode was used (streaming only)
gen_ai.conversation.idSession identifier
gen_ai.response.finish_reasonsStop reasons
gen_ai.response.idResponse ID
gen_ai.response.modelResolved model
gen_ai.response.time_to_first_chunkTime to first streaming chunk, in seconds (streaming only)
gen_ai.usage.cache_write.input_tokensCached tokens written
gen_ai.usage.cache_read.input_tokensCached tokens read
gen_ai.usage.input_tokensInput tokens this turn
gen_ai.usage.output_tokensOutput tokens this turn
gen_ai.usage.reasoning.output_tokensReasoning output tokens this turn
github.copilot.request.typeSet to compaction on spans emitted for conversation compaction
github.copilot.costPer-request model multiplier used for billing. Not a monetary value.
github.copilot.nano_aiuAI units consumed this turn, in nano AI units (1 AIU = 1,000,000,000 nano AIU)
github.copilot.server_durationServer-side duration
github.copilot.initiatorRequest initiator
github.copilot.turn_idTurn identifier
github.copilot.interaction_idInteraction identifier
server.addressServer hostname
server.portServer port
error.typeError class name (on error)
gen_ai.input.messagesFull prompt messages as JSON (content capture only)
gen_ai.output.messagesFull response messages as JSON (content capture only)
gen_ai.system_instructionsSystem prompt content as JSON (content capture only)

execute_tool span attributes

One span per tool call. Span kind: INTERNAL.

AttributeDescription
gen_ai.operation.nameexecute_tool
gen_ai.provider.nameProvider name (when available)
gen_ai.tool.nameTool name (for example, readFile)
gen_ai.tool.typefunction
gen_ai.tool.call.idTool call identifier
gen_ai.tool.descriptionTool description
error.typeError class name (on error)
gen_ai.tool.call.argumentsTool input arguments as JSON (content capture only)
gen_ai.tool.call.resultTool output as JSON (content capture only)

Hinweis

To measure AI unit consumption, read github.copilot.nano_aiu from the root invoke_agent span only. The attribute is also stamped on the child chat spans, so summing it across every span double-counts. github.copilot.cost is a per-request model multiplier used for billing calculations—it is not a currency value and must not be interpreted as one.

Metrics

The following metrics are emitted.

GenAI convention metrics

MetricTypeUnitDescription
gen_ai.client.operation.durationHistogramsDuration of a GenAI operation other than inference
gen_ai.client.inference.durationHistogramsDuration of a single LLM API call
gen_ai.client.inference.operation.input_tokensHistogram{token}Input tokens per model call
gen_ai.client.inference.operation.output_tokensHistogram{token}Output tokens per model call
gen_ai.client.inference.usage.input_tokensCounter{token}Input tokens used, including cached tokens
gen_ai.client.inference.usage.output_tokensCounter{token}Output tokens used, including reasoning tokens
gen_ai.client.inference.usage.cache_read.input_tokensCounter{token}Input tokens served from a provider-managed cache
gen_ai.client.inference.usage.cache_write.input_tokensCounter{token}Input tokens written to a provider-managed cache
gen_ai.client.inference.usage.reasoning.output_tokensCounter{token}Output tokens used for reasoning
gen_ai.client.inference.time_to_first_chunkHistogramsTime to receive the first chunk of a streaming response
gen_ai.client.inference.time_per_output_chunkHistogramsInter-chunk latency after the first chunk
gen_ai.invoke_agent.durationHistogramsEnd-to-end duration of one agent invocation
gen_ai.invoke_agent.inference_callsHistogram{inference_call}Number of model calls made during one agent invocation, counted at provider dispatch (failed and partial calls included; requests blocked before dispatch excluded). Dimension: gen_ai.agent.name.
gen_ai.invoke_agent.tool_callsHistogram{tool_call}Number of client-side tool calls made during one agent invocation (failed and partial calls included; synthetic tool lifecycles and provider-executed server-side tools excluded). Dimension: gen_ai.agent.name.
gen_ai.execute_tool.durationHistogramsDuration of a single tool execution
gen_ai.invoke_workflow.durationHistogramsEnd-to-end duration of a GenAI workflow (for example, a fleet mode run orchestrating parallel subagents).

Token metrics aggregate foreground and compaction work. github.copilot.request.type is a span attribute only, so it is not available as a metric dimension for separating them.

Vendor-specific metrics

MetricTypeUnitDescription
github.copilot.tool.call.countCounter{call}Tool invocations by gen_ai.tool.name and success
github.copilot.tool.call.durationHistogramsTool execution latency by gen_ai.tool.name
github.copilot.agent.turn.countHistogram{turn}LLM round-trips per agent invocation
github.copilot.mcp.server.connection.countCounter{attempt}Completed MCP server connection attempts by transport and outcome
github.copilot.code.lines_addedCounter{line}Lines added by file-editing tools, recorded in real time
github.copilot.code.lines_removedCounter{line}Lines removed by file-editing tools, recorded in real time
github.copilot.sandbox.operation.countCounter{decision}Bounded sandbox governance decisions, deduplicated
github.copilot.sandbox.spawn.durationHistogramsSandboxed process spawn latency
github.copilot.sandbox.policy.path.countHistogram{path}Effective filesystem policy paths by access class

Hinweis

Sandbox metrics are bounded operational signals, not a complete audit log. An unchanged policy resolution is deduplicated rather than counted again, and these metrics never carry file paths, commands, or proxy URLs as dimensions.

Span events

Key lifecycle events recorded on the active chat or invoke_agent span. This is not an exhaustive list; the runtime also emits sandbox governance events and additional session events.

EventDescriptionKey attributes
github.copilot.hook.startA hook began executinggithub.copilot.hook.type, github.copilot.hook.invocation_id
github.copilot.hook.endA hook completed successfullygithub.copilot.hook.type, github.copilot.hook.invocation_id
github.copilot.hook.errorA hook failedgithub.copilot.hook.type, github.copilot.hook.invocation_id, github.copilot.hook.error_message
github.copilot.session.truncationConversation history was truncatedgithub.copilot.token_limit, github.copilot.pre_tokens, github.copilot.post_tokens, github.copilot.pre_messages, github.copilot.post_messages, github.copilot.tokens_removed, github.copilot.messages_removed, github.copilot.performed_by
github.copilot.session.compaction_startHistory compaction beganNone
github.copilot.session.compaction_completeHistory compaction completedgithub.copilot.success, github.copilot.pre_tokens, github.copilot.post_tokens, github.copilot.tokens_removed, github.copilot.messages_removed, github.copilot.message (content capture only)
github.copilot.skill.invokedA skill was invokedgithub.copilot.skill.name, github.copilot.skill.path, github.copilot.skill.plugin_name, github.copilot.skill.plugin_version
github.copilot.session.shutdownSession is shutting downgithub.copilot.shutdown_type, github.copilot.total_premium_requests, github.copilot.lines_added, github.copilot.lines_removed, github.copilot.files_modified_count
github.copilot.session.abortUser cancelled the current operationgithub.copilot.abort_reason
gen_ai.client.operation.exceptionSession errorgithub.copilot.error_type, github.copilot.error_status_code, github.copilot.error_provider_call_id

Resource attributes

All signals carry these resource attributes.

AttributeValue
service.namegithub-copilot (configurable via OTEL_SERVICE_NAME)
service.versionRuntime version

Content capture

By default, no prompt content, responses, or tool arguments are captured—only metadata like model names, token counts, and durations. To capture full content, set OTEL_INSTRUMENTATION_GENAI_CAPTURE_CONTENT to SPAN_ONLY or SPAN_AND_EVENT. The values NO_CONTENT (the default) and EVENT_ONLY leave span content capture off.

If OTEL_INSTRUMENTATION_GENAI_CAPTURE_CONTENT is empty or unset, the runtime falls back to the legacy boolean variable OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT. An unrecognized value for the standard variable disables span content capture and logs a warning.

Warnung

Content capture may include sensitive information such as code, file contents, and user prompts. Only enable this in trusted environments.

When content capture is enabled, the following attributes are populated.

AttributeContent
gen_ai.input.messagesFull prompt messages (JSON)
gen_ai.output.messagesFull response messages (JSON)
gen_ai.system_instructionsSystem prompt content (JSON)
gen_ai.tool.definitionsTool schemas (JSON). Schema metadata keeps an independent opt-in: this attribute is populated only by the legacy OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT variable, not by OTEL_INSTRUMENTATION_GENAI_CAPTURE_CONTENT.
gen_ai.tool.call.argumentsTool input arguments
gen_ai.tool.call.resultTool output