Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1ae83f2
docs: add enterprise OTel managed-settings policy plan
zhichli Jun 26, 2026
b2ca1ff
docs: note policyReference type-match constraint and structured-encod…
zhichli Jun 26, 2026
cb4f2a8
feat: add enterprise OTel telemetry managed-settings keys and respons…
zhichli Jun 26, 2026
afd5338
feat: gate agent-host OTel settings with enterprise managed-settings …
zhichli Jun 26, 2026
74333cf
feat: apply enterprise OTel policy precedence in copilot-chat extension
zhichli Jun 26, 2026
42a2f6b
test: cover enterprise OTel policy precedence in resolveOTelConfig
zhichli Jun 26, 2026
a3930b8
build: export OTel managed-settings policies to policy catalog
zhichli Jun 26, 2026
d0ba9fc
docs: add OTel managed-settings sprint plan with completion notes
zhichli Jun 26, 2026
4cf2f3e
feat: honor managed OTLP wire protocol (protobuf/json) in agent host env
zhichli Jun 26, 2026
7f142af
build: export CopilotOtelOtlpProtocol policy to catalog
zhichli Jun 26, 2026
bdbe1f0
feat: honor managed OTLP protobuf wire protocol in copilot-chat exten…
zhichli Jun 26, 2026
401a8ca
build: link otel.protocol reference in policy catalog
zhichli Jun 26, 2026
4be6140
docs: update OTel managed-settings plan/sprint for protocol parity
zhichli Jun 26, 2026
276c471
fix: deliver managed OTel policy to the desktop agent host
zhichli Jun 26, 2026
0fdb82f
docs: revise OTel managed-settings sprint plan for headers/resourceAt…
zhichli Jun 26, 2026
ee15dee
feat: deliver managed OTel serviceName to both surfaces
zhichli Jun 26, 2026
fce8c4f
feat: deliver managed OTel resourceAttributes to both surfaces
zhichli Jun 26, 2026
bb52401
feat: deliver managed OTel headers to the Copilot Chat extension
zhichli Jun 26, 2026
6410d9e
docs: record serviceName/resourceAttributes/headers delivery in sprint
zhichli Jun 26, 2026
65bcc23
docs: remove internal OTel managed-settings planning notes
zhichli Jun 26, 2026
597760e
Merge remote-tracking branch 'origin/main' into zhichli/otelpolicy2
zhichli Jun 27, 2026
649467a
fix: align agentOTelEnv test config with widened otlpProtocol type
zhichli Jun 27, 2026
e9a2553
refactor: address PR review — policy precedence docs, grpc transport …
zhichli Jun 27, 2026
7b0180b
docs: update OTel user + agent-host docs for managed-settings precede…
zhichli Jun 27, 2026
e5ec5ab
fix: register otel protocol/serviceName/resourceAttributes/headers co…
zhichli Jun 27, 2026
0ce1f55
fix: regenerate policy data to match fixture-based export
zhichli Jun 27, 2026
997c378
docs(add-policy): warn that policyData must be regenerated in a clean…
zhichli Jun 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/skills/add-policy/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,4 +328,5 @@ Search the codebase for `policy:` to find all the examples of different policy c
## Learnings

* Never hand-edit `build/lib/policies/policyData.jsonc` (its header explicitly forbids it). If `npm run export-policy-data` is failing, fix the script — don't patch the JSON. Common cause: running it in the wrong working directory (e.g. main repo instead of a worktree), which silently exports the wrong source tree.
* **Regenerate `policyData.jsonc` in a clean environment, or the `PolicyExport` integration test will fail in CI.** `referencedSettings` is only captured for references **loaded at export time**. A plain `npm run export-policy-data` loads your **dev-profile extensions** (e.g. the Copilot extension), which injects `referencedSettings` onto core policies that the test's **fixture-based** export (clean profile, no user extensions) won't produce — so the checked-in file ends up with extra `referencedSettings` and CI fails. This is **not reproducible locally** because the test reuses your default extensions dir. Regenerate the way the test exports: `DISTRO_PRODUCT_JSON=<extensionPolicyFixture.json> ./scripts/code.sh --export-policy-data="$PWD/build/lib/policies/policyData.jsonc" --user-data-dir="$(mktemp -d)" --extensions-dir="$(mktemp -d)"` (with `VSCODE_SKIP_PRELAUNCH=1`).
* Document **behavior and business-logic expectations**, not copy-pasted implementation. Reproducing internal code (e.g. the `getPolicyData()` merge body) in the skill rots the moment the source changes and adds no information beyond the source itself. State the contract in prose (e.g. "server-delivered managed settings win over native MDM; the two layers are never merged") and point to the source for the implementation. Reserve code blocks for the **author-facing API contract** a contributor must follow — how to *declare* a `policy` / `managedSettings` / `value` callback — not for restating runtime plumbing.
187 changes: 173 additions & 14 deletions build/lib/policies/policyData.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,66 @@
}
],
"policies": [
{
"key": "chat.agentHost.otel.otlpProtocol",
"name": "CopilotOtelOtlpProtocol",
"category": "InteractiveSession",
"minimumVersion": "1.127",
"localization": {
"description": {
"key": "chat.agentHost.otel.otlpProtocol.policy",
"value": "Controls the enterprise-managed OTLP wire protocol (protobuf vs JSON) for Copilot OpenTelemetry export."
}
},
"type": "string",
"default": "",
"included": false
},
{
"key": "chat.agentHost.otel.serviceName",
"name": "CopilotOtelServiceName",
"category": "InteractiveSession",
"minimumVersion": "1.127",
"localization": {
"description": {
"key": "chat.agentHost.otel.serviceName.policy",
"value": "Controls the enterprise-managed OTel `service.name` resource attribute for Copilot OpenTelemetry export."
}
},
"type": "string",
"default": "",
"included": false
},
{
"key": "chat.agentHost.otel.resourceAttributes",
"name": "CopilotOtelResourceAttributes",
"category": "InteractiveSession",
"minimumVersion": "1.127",
"localization": {
"description": {
"key": "chat.agentHost.otel.resourceAttributes.policy",
"value": "Controls the enterprise-managed OTel resource attributes for Copilot OpenTelemetry export."
}
},
"type": "object",
"default": {},
"included": false
},
{
"key": "chat.agentHost.otel.headers",
"name": "CopilotOtelHeaders",
"category": "InteractiveSession",
"minimumVersion": "1.127",
"localization": {
"description": {
"key": "chat.agentHost.otel.headers.policy",
"value": "Controls the enterprise-managed OTLP exporter headers for Copilot OpenTelemetry export."
}
},
"type": "object",
"default": {},
"included": false
},
{
"key": "mcp.enterpriseManagedAuth.idp",
"name": "McpEnterpriseManagedAuthIdp",
Expand Down Expand Up @@ -143,6 +203,24 @@
"default": true,
"included": true
},
{
"key": "chat.agentHost.claudeAgent.enabled",
"name": "Claude3PIntegration",
"category": "InteractiveSession",
"minimumVersion": "1.113",
"localization": {
"description": {
"key": "chat.agentHost.claudeAgent.enabled.policy",
"value": "Enable Claude Agent sessions in VS Code. Start and resume agentic coding sessions powered by Anthropic Claude Agent SDK directly in the editor. Uses your existing Copilot subscription."
}
},
"type": "boolean",
"default": true,
"included": true,
"referencedSettings": [
"github.copilot.chat.claudeAgent.enabled"
]
},
{
"key": "chat.agentHost.codexAgent.enabled",
"name": "Codex3PIntegration",
Expand All @@ -159,37 +237,118 @@
"included": true
},
{
"key": "chat.defaultModel",
"name": "ChatDefaultModel",
"key": "chat.agentHost.otel.enabled",
"name": "CopilotOtelEnabled",
"category": "InteractiveSession",
"minimumVersion": "1.127",
"localization": {
"description": {
"key": "chat.defaultModel.policy",
"value": "Sets the default chat model for new conversations. Accepts \"auto\", a model family name (such as \"opus\" or \"gemini\"), or a full model id. Users can still switch the model within a conversation."
"key": "chat.agentHost.otel.enabled.policy",
"value": "Controls whether Copilot OpenTelemetry export is enabled. When managed, users cannot override the enterprise value."
}
},
"type": "boolean",
"default": false,
"included": true
},
{
"key": "chat.agentHost.otel.exporterType",
"name": "CopilotOtelProtocol",
"category": "InteractiveSession",
"minimumVersion": "1.127",
"localization": {
"description": {
"key": "chat.agentHost.otel.protocol.policy",
"value": "Controls the enterprise-managed OTLP protocol for Copilot OpenTelemetry export."
},
"enumDescriptions": [
{
"key": "chat.agentHost.otel.protocol.policy.otlpHttp",
"value": "Use OTLP over HTTP."
},
{
"key": "chat.agentHost.otel.protocol.policy.otlpGrpc",
"value": "Use OTLP over gRPC."
},
{
"key": "chat.agentHost.otel.protocol.policy.console",
"value": "Console exporter is not selected by enterprise managed settings."
},
{
"key": "chat.agentHost.otel.protocol.policy.file",
"value": "File exporter is not selected by enterprise managed settings."
}
]
},
"type": "string",
"default": "otlp-http",
"enum": [
"otlp-http",
"otlp-grpc",
"console",
"file"
],
"included": true
},
{
"key": "chat.agentHost.otel.otlpEndpoint",
"name": "CopilotOtelEndpoint",
"category": "InteractiveSession",
"minimumVersion": "1.127",
"localization": {
"description": {
"key": "chat.agentHost.otel.otlpEndpoint.policy",
"value": "Controls the enterprise-managed OTLP collector endpoint for Copilot OpenTelemetry export."
}
},
"type": "string",
"default": "",
"included": true
},
{
"key": "chat.agentHost.claudeAgent.enabled",
"name": "Claude3PIntegration",
"key": "chat.agentHost.otel.captureContent",
"name": "CopilotOtelCaptureContent",
"category": "InteractiveSession",
"minimumVersion": "1.113",
"minimumVersion": "1.127",
"localization": {
"description": {
"key": "chat.agentHost.claudeAgent.enabled.policy",
"value": "Enable Claude Agent sessions in VS Code. Start and resume agentic coding sessions powered by Anthropic Claude Agent SDK directly in the editor. Uses your existing Copilot subscription."
"key": "chat.agentHost.otel.captureContent.policy",
"value": "Controls whether Copilot OpenTelemetry export captures prompt, response, and tool content."
}
},
"type": "boolean",
"default": true,
"included": true,
"referencedSettings": [
"github.copilot.chat.claudeAgent.enabled"
]
"default": false,
"included": true
},
{
"key": "chat.agentHost.otel.outfile",
"name": "CopilotOtelOutfile",
"category": "InteractiveSession",
"minimumVersion": "1.127",
"localization": {
"description": {
"key": "chat.agentHost.otel.outfile.policy",
"value": "Prevents local file export when enterprise-managed Copilot OpenTelemetry export is configured."
}
},
"type": "string",
"default": "",
"included": true
},
{
"key": "chat.defaultModel",
"name": "ChatDefaultModel",
"category": "InteractiveSession",
"minimumVersion": "1.127",
"localization": {
"description": {
"key": "chat.defaultModel.policy",
"value": "Sets the default chat model for new conversations. Accepts \"auto\", a model family name (such as \"opus\" or \"gemini\"), or a full model id. Users can still switch the model within a conversation."
}
},
"type": "string",
"default": "",
"included": true
},
{
"key": "chat.tools.global.autoApprove",
Expand Down
13 changes: 9 additions & 4 deletions extensions/copilot/docs/monitoring/agent_monitoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Open **Settings** (`Ctrl+,`) and add:
}
```

> **Note:** You can also use environment variables instead of VS Code settings (see [Configuration](#configuration)). Environment variables always take precedence.
> **Note:** You can also use environment variables instead of VS Code settings (see [Configuration](#configuration)). Precedence is **enterprise policy > environment variables > settings**.

### 3. Generate Telemetry

Expand Down Expand Up @@ -70,13 +70,17 @@ Open **Settings** (`Ctrl+,`) and search for `copilot otel`:
| `github.copilot.chat.otel.exporterType` | string | `"otlp-http"` | `otlp-http`, `otlp-grpc`, `console`, or `file` |
| `github.copilot.chat.otel.otlpEndpoint` | string | `"http://localhost:4318"` | OTLP collector endpoint |
| `github.copilot.chat.otel.captureContent` | boolean | `false` | Capture full prompt/response content |
| `github.copilot.chat.otel.protocol` | string | `""` | OTLP wire protocol: `http/json` (default), `http/protobuf`, or `grpc` |
| `github.copilot.chat.otel.serviceName` | string | `""` | Override the `service.name` resource attribute |
| `github.copilot.chat.otel.resourceAttributes` | object | `{}` | Extra resource attributes (`{ "key": "value" }`) |
| `github.copilot.chat.otel.headers` | object | `{}` | Extra OTLP exporter headers, applied directly to the exporter (`{ "key": "value" }`) |
| `github.copilot.chat.otel.maxAttributeSizeChars` | integer | `0` | Max characters per OTel content attribute (prompts, tool args/results, hook input/output). `0` (the default) disables truncation so backends with no per-attribute limit get full payloads. Set to a positive value to match your backend's per-attribute size limit — consult your backend's documentation. The value counts JavaScript string characters (UTF-16 code units); for non-ASCII content one character can be multiple UTF-8 bytes on the wire. |
| `github.copilot.chat.otel.outfile` | string | `""` | File path for JSON-lines output |
| `github.copilot.chat.otel.dbSpanExporter.enabled` | boolean | `false` | Persist OTel spans to a local SQLite database for the **Chat: Export Agent Traces DB** command. Implicitly enables OTel. |

### Environment Variables

Environment variables **always take precedence** over VS Code settings.
Environment variables take precedence over VS Code settings, and **enterprise managed settings (policy) take precedence over both** — admins can centrally mandate any `github.copilot.chat.otel.*` value.

| Variable | Default | Description |
|---|---|---|
Expand All @@ -98,6 +102,7 @@ Environment variables **always take precedence** over VS Code settings.

OTel is **off by default** with zero overhead. It activates when:

- enterprise policy enables it (managed `telemetry.enabled` or a managed endpoint), or
- `COPILOT_OTEL_ENABLED=true`, or
- `OTEL_EXPORTER_OTLP_ENDPOINT` is set, or
- `github.copilot.chat.otel.enabled` is `true`, or
Expand Down Expand Up @@ -471,7 +476,7 @@ All signals carry:

| Attribute | Value |
|---|---|
| `service.name` | `copilot-chat` (configurable via `OTEL_SERVICE_NAME`) |
| `service.name` | `copilot-chat` (override via the `github.copilot.chat.otel.serviceName` setting, `OTEL_SERVICE_NAME`, or enterprise policy) |
| `service.version` | Extension version |
| `session.id` | Unique per VS Code window |

Expand Down Expand Up @@ -541,7 +546,7 @@ Content is captured in full with no truncation.
}
```

> **Note:** Authentication headers are only configurable via the `OTEL_EXPORTER_OTLP_HEADERS` environment variable (e.g., `Authorization=Bearer your-token`). See [Environment Variables](#environment-variables).
> **Note:** Authentication headers can be set via the `github.copilot.chat.otel.headers` setting (a `{ "key": "value" }` map applied directly to the exporter) or the `OTEL_EXPORTER_OTLP_HEADERS` environment variable, and can be mandated by enterprise policy. See [Environment Variables](#environment-variables).

**File-based output (offline / CI):**

Expand Down
12 changes: 8 additions & 4 deletions extensions/copilot/docs/monitoring/agent_monitoring_arch.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,13 @@ Both export to the same OTLP endpoint. Bridge processor sits on Provider B, forw

`resolveOTelConfig()` implements layered precedence:

1. `COPILOT_OTEL_*` env vars (highest)
2. `OTEL_EXPORTER_OTLP_*` standard env vars
3. VS Code settings (`github.copilot.chat.otel.*`)
4. Defaults (lowest)
1. Enterprise managed settings (policy) — highest; overrides env vars
2. `COPILOT_OTEL_*` env vars
3. `OTEL_EXPORTER_OTLP_*` standard env vars
4. VS Code settings (`github.copilot.chat.otel.*`)
5. Defaults (lowest)

The OTLP wire protocol distinguishes `http/json` (default) from `http/protobuf`; `grpc` is selected by the gRPC exporter type.

Kill switch: `telemetry.telemetryLevel === 'off'` → all OTel disabled.

Expand All @@ -222,6 +225,7 @@ The resolved config records *how* OTel was enabled in `OTelConfig.enabledVia` (u

| `enabledVia` | Trigger |
|---|---|
| `policy` | Enterprise managed settings enable OTel (`telemetry.enabled` or a managed endpoint) |
| `envVar` | `COPILOT_OTEL_ENABLED=true` |
| `setting` | `github.copilot.chat.otel.enabled` is `true` |
| `otlpEndpointEnvVar` | `OTEL_EXPORTER_OTLP_ENDPOINT` is set without an explicit enable |
Expand Down
Loading
Loading