GitHub Copilot
Send GitHub Copilot Chat and Copilot SDK telemetry — LLM calls, tool executions, token usage, and latency — to Last9 via OpenTelemetry.
GitHub Copilot emits structured OpenTelemetry telemetry for agent sessions: LLM calls, tool executions, token usage, and latency. Routing this data to Last9 gives you visibility into how your team uses Copilot — without custom instrumentation.
Copilot follows OpenTelemetry GenAI semantic conventions, so spans and metrics use standardized attribute names compatible with any OTel backend, including Last9.
There are two ways to export Copilot telemetry to Last9:
| Path | Who it’s for | Setup |
|---|---|---|
| Copilot Chat (VS Code extension) | Teams using Copilot in VS Code — agent mode, inline chat, CLI sessions | VS Code settings or environment variables → Last9 OTLP |
| Copilot SDK (custom agents) | Teams building custom agents with CopilotClient | TelemetryConfig in your agent code → Last9 OTLP |
What gets exported
Traces
Each agent interaction produces a hierarchical span tree:
invoke_agent [~15s] ├── chat gpt-4o [~3s] ├── execute_tool readFile [~50ms] ├── execute_tool runCommand [~2s] └── chat gpt-4o [~4s]When an agent invokes a subagent (for example via runSubagent), the subagent’s invoke_agent span is parented under the calling execute_tool span.
| Span | Description | Key attributes |
|---|---|---|
invoke_agent | Root span wrapping the entire agent turn | gen_ai.operation.name, gen_ai.agent.name, gen_ai.conversation.id, error.type |
chat | Single LLM API call within the agent | gen_ai.request.model, gen_ai.usage.input_tokens, gen_ai.usage.output_tokens, gen_ai.response.finish_reasons |
execute_tool | Single tool invocation | gen_ai.tool.name, gen_ai.tool.call.id, error.type |
Prompt and response content is not captured by default. Enable content capture to opt in — see Configuration reference.
Metrics
| Metric | Type | Description |
|---|---|---|
gen_ai.client.operation.duration | Histogram | LLM API call latency |
gen_ai.client.token.usage | Counter | Input and output token counts |
copilot_chat.tool.call.count | Counter | Number of tool invocations |
copilot_chat.tool.call.duration | Histogram | Tool execution latency |
copilot_chat.agent.invocation.duration | Histogram | End-to-end agent turn latency |
copilot_chat.agent.turn.count | Counter | Total agent turns |
copilot_chat.session.count | Counter | Total sessions started |
copilot_chat.time_to_first_token | Histogram | Streaming TTFT (streaming only) |
Events
Copilot Chat also emits OTel events for session starts, tool completions, edit accept/reject feedback, and user thumbs-up/down — useful for acceptance-rate dashboards alongside traces.
Prerequisites
- Last9 account — Sign up at app.last9.io
- GitHub Copilot subscription — Individual, Business, or Enterprise plan
- OTLP credentials — Get your endpoint and auth header from Integrations → OpenTelemetry
Copilot Chat (VS Code)
Use this path when developers use Copilot inside VS Code — agent mode, inline chat, or Copilot CLI sessions launched from the editor.
Additional prerequisites
- VS Code 1.119+
- Copilot Chat extension with OTel support (update to the latest version)
Setup
-
Get your Last9 OTLP credentials
Navigate to Integrations → OpenTelemetry in your Last9 dashboard. Copy:
- OTLP Endpoint (e.g.,
https://otlp-aps1.last9.io:443) - Authorization header (e.g.,
Basic <base64-token>)
- OTLP Endpoint (e.g.,
-
Enable OTel export
OTel activates when any of these is true:
github.copilot.chat.otel.enabledistrueCOPILOT_OTEL_ENABLED=trueOTEL_EXPORTER_OTLP_ENDPOINTis set
Export these variables before launching VS Code (or set them in your shell profile / enterprise launch script):
export COPILOT_OTEL_ENABLED=trueexport OTEL_EXPORTER_OTLP_ENDPOINT="https://<your-last9-otlp-endpoint>"export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <your-last9-auth-token>"export OTEL_SERVICE_NAME="copilot-chat"export OTEL_RESOURCE_ATTRIBUTES="deployment.environment=production,team=<your-team>"Environment variables take precedence over VS Code settings.
Open Settings (
Cmd+,/Ctrl+,) and search forcopilot otel:Setting Value github.copilot.chat.otel.enabledtruegithub.copilot.chat.otel.exporterTypeotlp-httpgithub.copilot.chat.otel.otlpEndpointhttps://<your-last9-otlp-endpoint>For the auth header, use the environment variable (settings UI does not expose headers):
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <your-last9-auth-token>"Push the same settings via Settings Sync, Group Policy, or your MDM-managed VS Code
settings.jsonso developers do not configure OTLP manually. Pair with a managed shell profile or launch script that exportsOTEL_EXPORTER_OTLP_HEADERS. -
Restart VS Code and send a test prompt
Open Copilot Chat in agent mode and send any prompt. Wait up to 60 seconds for the first metrics flush.
-
Verify in Last9
- Traces — filter by
service.name = copilot-chatand look forinvoke_agentroot spans - Metrics — search for
copilot_chat_agent_invocation_durationorgen_ai_client_token_usage - Distinguish agent types — filter spans by
gen_ai.agent.name:GitHub Copilot Chat— foreground agent (agent mode)copilotcli— CLI wrapper spanclaude— Claude agent sessions proxied through VS Code
- Traces — filter by
Copilot Chat configuration reference
| VS Code setting | Env var | Default | Description |
|---|---|---|---|
github.copilot.chat.otel.enabled | COPILOT_OTEL_ENABLED | false | Enable OTel emission |
github.copilot.chat.otel.otlpEndpoint | OTEL_EXPORTER_OTLP_ENDPOINT, COPILOT_OTEL_ENDPOINT | http://localhost:4318 | Last9 OTLP endpoint |
github.copilot.chat.otel.exporterType | — | otlp-http | Use otlp-http for Last9 |
github.copilot.chat.otel.captureContent | COPILOT_OTEL_CAPTURE_CONTENT | false | Include prompts and responses in spans |
| — | OTEL_SERVICE_NAME | copilot-chat | Service name in Last9 |
| — | OTEL_RESOURCE_ATTRIBUTES | — | Team, environment, or org tags |
| — | OTEL_EXPORTER_OTLP_HEADERS | — | Authorization=Basic <token> |
Copilot SDK (custom agents)
Use this path when you build custom agents with the GitHub Copilot SDK and CopilotClient.
Additional prerequisites
- GitHub token — A user-level token with a Copilot subscription behind it:
- Fine-grained PAT (
github_pat_*) — easiest for local dev - GitHub App user access token (
ghu_*) — recommended for production - Classic PATs (
ghp_*) and GitHub App installation tokens are not accepted
- Fine-grained PAT (
- Copilot SDK — Installed in your agent project (Node.js, Python, Go, or .NET)
Setup
-
Get your Last9 OTLP credentials — same as Copilot Chat above.
-
Install the SDK with telemetry support
npm install @github/copilot-sdkpip install "copilot-sdk[telemetry]"go get github.com/github/copilot-sdk-godotnet add package GitHub.Copilot.SDK -
Configure telemetry in your agent
Pass a
TelemetryConfigwhen constructing theCopilotClient. Set theotlpEndpointto your Last9 OTLP endpoint and include your authorization header.import { CopilotClient } from "@github/copilot-sdk";const client = new CopilotClient({telemetry: {exporterType: "otlp-http",otlpEndpoint: "https://<your-last9-otlp-endpoint>",sourceName: "my-copilot-agent",captureContent: false,},});export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <your-last9-auth-token>"export OTEL_SERVICE_NAME="my-copilot-agent"from copilot_sdk import CopilotClient, SubprocessConfigclient = CopilotClient(SubprocessConfig(telemetry={"exporter_type": "otlp-http","otlp_endpoint": "https://<your-last9-otlp-endpoint>","source_name": "my-copilot-agent","capture_content": False,}))export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <your-last9-auth-token>"export OTEL_SERVICE_NAME="my-copilot-agent"import copilot "github.com/github/copilot-sdk-go"client, err := copilot.NewClient(copilot.ClientConfig{Telemetry: &copilot.TelemetryConfig{ExporterType: "otlp-http",OTLPEndpoint: "https://<your-last9-otlp-endpoint>",SourceName: "my-copilot-agent",CaptureContent: false,},})export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <your-last9-auth-token>"export OTEL_SERVICE_NAME="my-copilot-agent"using GitHub.Copilot.SDK;var client = new CopilotClient(new ClientConfig{Telemetry = new TelemetryConfig{ExporterType = "otlp-http",OtlpEndpoint = "https://<your-last9-otlp-endpoint>",SourceName = "my-copilot-agent",CaptureContent = false,}});export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <your-last9-auth-token>"export OTEL_SERVICE_NAME="my-copilot-agent" -
Invoke your agent and verify data
Run your agent and trigger at least one interaction. Then in Last9:
- Traces — filter by
service.name = my-copilot-agentand look forinvoke_agentroot spans - Metrics — search for
copilot_chat_agent_invocation_duration
- Traces — filter by
SDK TelemetryConfig fields
| Field | Type | Default | Description |
|---|---|---|---|
exporterType | string | "otlp-http" | "otlp-http" to send to Last9; "file" to write JSON-lines locally |
otlpEndpoint | string | — | Last9 OTLP endpoint (HTTP, port 443) |
filePath | string | — | Output path when exporterType is "file" |
sourceName | string | — | Instrumentation scope name — appears as the tracer name in Last9 |
captureContent | boolean | false | Include prompt text and model responses in spans |
Org-level Copilot metrics (coming soon)
GitHub also exposes organization-level Copilot metrics — seat utilization, acceptance rates, and language breakdown — via the Copilot metrics API. Last9 is adding ingestion of these metrics through the Last9 GitHub App so platform teams can see org-wide Copilot adoption without per-developer OTLP setup.
This complements per-session traces from Copilot Chat; it does not replace them.
What you can do in Last9
Agent latency breakdown (traces)
Each invoke_agent span contains child chat and execute_tool spans. In Last9 APM, expand a trace to see how much time was spent on LLM calls versus tool execution within a single agent turn.
Token and cost tracking (metrics)
gen_ai.client.token.usage is broken down by gen_ai.request.model. Use it to compare token consumption across models, track usage trends, and alert on spikes.
Tool performance (metrics)
copilot_chat.tool.call.duration and copilot_chat.tool.call.count show which tools are called most and which are slowest.
Error rate monitoring (traces)
Failed LLM calls and tool executions set error.type on their spans. Create a Last9 alert on error rate for invoke_agent spans to catch Copilot API degradation before users report it.
Team tagging
Use OTEL_RESOURCE_ATTRIBUTES to tag sessions by team or environment:
export OTEL_RESOURCE_ATTRIBUTES="team=platform,deployment.environment=production"All signals from that developer’s VS Code session carry these labels, enabling per-team breakdowns in Last9 dashboards.
Troubleshooting
-
No traces in Last9 after a Copilot Chat session
- Confirm VS Code is 1.119+ and Copilot Chat is updated
- Confirm
github.copilot.chat.otel.enabledistrueorCOPILOT_OTEL_ENABLED=true - Restart VS Code after setting environment variables — VS Code must inherit
OTEL_EXPORTER_OTLP_*at launch - Verify the endpoint has no trailing path (use
https://otlp-aps1.last9.io:443, not.../v1/traces) - Send at least one agent-mode prompt and wait up to 60 seconds
-
No traces from a Copilot SDK agent
- Confirm
exporterType: "otlp-http"— double-check it is not set to"file" - Check that
OTEL_EXPORTER_OTLP_HEADERSis exported in the same shell session where the agent runs
- Confirm
-
401 / authentication errors
- Verify the header format:
Authorization=Basic <token>(no extra quotes, noBearerprefix) - Regenerate the token from Integrations → OpenTelemetry if it has expired
- Verify the header format:
-
Spans appear but no metrics
- Metrics may take up to 60 seconds to flush after the first invocation
- Confirm the Copilot Chat extension or SDK version supports metrics export
-
Content is missing from spans
- By default, prompts and responses are not captured — set
github.copilot.chat.otel.captureContentorcaptureContent: truein SDK config
- By default, prompts and responses are not captured — set
Please get in touch with us on Discord or Email if you have any questions.