Summary
The Copilot CLI subprocess (spawned by github-copilot-sdk v0.2.2) correctly applies OTEL_RESOURCE_ATTRIBUTES to spans but does not apply them to metrics emitted from the same process. This makes per-run / per-tenant attribution impossible for metric-backed dashboards.
Reproduction
- Set custom resource attributes before spawning the SDK / starting the CLI:
export OTEL_SERVICE_NAME=workflow-skeleton
export OTEL_RESOURCE_ATTRIBUTES=workflow.run_kind=resume
export OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.eu01.nr-data.net
export OTEL_EXPORTER_OTLP_HEADERS="api-key=..."
- Run any workflow that produces both spans and metrics from the subprocess (
chat, execute_tool, etc.).
- Query the backend for spans and metrics where
otel.library.name = 'github.copilot'.
Observed (New Relic NRQL, EU)
Spans — Resource attribute is present:
FROM Span SELECT count(*) WHERE otel.library.name = 'github.copilot'
FACET workflow.run_kind SINCE 6 hours ago
-- => resume: 41
Metrics — Resource attribute is missing:
FROM Metric SELECT keyset() WHERE metricName = 'gen_ai.client.token.usage' SINCE 6 hours ago
-- => keys: service.name, service.version, gen_ai.*, otel.library.name, ...
-- NO workflow.run_kind
FROM Metric SELECT count(*) WHERE metricName = 'gen_ai.client.token.usage' SINCE 24 hours ago
FACET workflow.run_kind
-- => only NULL bucket
service.name (set via OTEL_SERVICE_NAME) does land on metrics, suggesting the MeterProvider is reading the dedicated env var but not the generic OTEL_RESOURCE_ATTRIBUTES.
Affected Metric Names
All metrics emitted by the subprocess with otel.library.name = 'github.copilot', including:
gen_ai.client.token.usage
gen_ai.client.operation.duration
github.copilot.tool.call.count
github.copilot.tool.call.duration
Expected
The subprocess MeterProvider should be initialized with the same Resource as the TracerProvider — typically by calling Resource.default().merge(Resource.fromEnvironment()) (or the equivalent in whichever SDK powers the binary), so that any OTEL_RESOURCE_ATTRIBUTES value is also applied to emitted metrics.
Impact
Downstream observability tools (dashboards, alerts, billing attribution) cannot filter or group LLM / tool-call metrics by per-invocation context (tenant, workflow run, run kind, environment, etc.). Spans can be filtered correctly, but metric-backed widgets — which are required for cardinality-friendly aggregations like rate, percentile, or distribution — return only the global / NULL bucket.
Environment
github-copilot-sdk==0.2.2
- Python 3.13
- macOS arm64
- Bundled CLI binary at
.venv/lib/python3.13/site-packages/copilot/bin/copilot (Mach-O arm64, packed)
Summary
The Copilot CLI subprocess (spawned by
github-copilot-sdkv0.2.2) correctly appliesOTEL_RESOURCE_ATTRIBUTESto spans but does not apply them to metrics emitted from the same process. This makes per-run / per-tenant attribution impossible for metric-backed dashboards.Reproduction
chat,execute_tool, etc.).otel.library.name = 'github.copilot'.Observed (New Relic NRQL, EU)
Spans — Resource attribute is present:
Metrics — Resource attribute is missing:
service.name(set viaOTEL_SERVICE_NAME) does land on metrics, suggesting the MeterProvider is reading the dedicated env var but not the genericOTEL_RESOURCE_ATTRIBUTES.Affected Metric Names
All metrics emitted by the subprocess with
otel.library.name = 'github.copilot', including:gen_ai.client.token.usagegen_ai.client.operation.durationgithub.copilot.tool.call.countgithub.copilot.tool.call.durationExpected
The subprocess MeterProvider should be initialized with the same
Resourceas the TracerProvider — typically by callingResource.default().merge(Resource.fromEnvironment())(or the equivalent in whichever SDK powers the binary), so that anyOTEL_RESOURCE_ATTRIBUTESvalue is also applied to emitted metrics.Impact
Downstream observability tools (dashboards, alerts, billing attribution) cannot filter or group LLM / tool-call metrics by per-invocation context (tenant, workflow run, run kind, environment, etc.). Spans can be filtered correctly, but metric-backed widgets — which are required for cardinality-friendly aggregations like rate, percentile, or distribution — return only the global / NULL bucket.
Environment
github-copilot-sdk==0.2.2.venv/lib/python3.13/site-packages/copilot/bin/copilot(Mach-O arm64, packed)