π€ This issue has been generated by Claude Code.
Summary
The MCP gateway (ghcr.io/github/gh-aw-mcpg) emits its spans (gateway.request, mcp.tool_call, gateway.backend.execute) with an empty OpenTelemetry Resource β no service.name, no attributes at all β because resource detection fails at gateway startup with a semconv schema-URL conflict. As a result, even though the gateway spans share the correct traceId and correctly point to the agent.setup span as their parent, observability backends that assemble/segment the waterfall per service cannot stitch them into the gh-aw trace. The gh-aw lifecycle spans render as one tree, and the gateway spans render as a separate, parent-less group of orphan roots.
Tested with gh-aw CLI v0.79.1, engine Claude Code 2.1.168, awf v0.25.68, gateway image ghcr.io/github/gh-aw-mcpg:v0.3.25.
(Note: the OTLP spans report this under an attribute literally named gh-aw.cli.version: 2.1.168, but per the run's aw_info.json that 2.1.168 is the Claude Code engine version β cli_version is v0.79.1. The gh-aw.cli.version span attribute therefore appears to carry the engine/agent version rather than the gh-aw CLI version. Tracked separately in #38897.)
Root cause: gateway resource detection fails β empty Resource
At gateway startup the OTLP tracer logs:
[tracing:provider] Initializing OTLP tracing: endpoint=https://<otlp-endpoint>/v1/traces, service=mcp-gateway, sampleRate=1.00
[tracing:provider] Warning: failed to create OTEL resource: error detecting resource: conflicting Schema URL: https://opentelemetry.io/schemas/1.34.0 and https://opentelemetry.io/schemas/1.41.0
[tracing:provider] OTLP tracing initialized successfully
The gateway intends service.name=mcp-gateway, but the schema-URL conflict (OTel semantic-conventions 1.34.0 vs 1.41.0 inside the gh-aw-mcpg binary) discards the entire Resource, so spans are exported with no service identity.
Evidence (OTLP/JSON received by a backend)
Same run, single OTLP endpoint, all spans received. Comparing the resourceSpans[].resource of the two span groups:
Crucially, the linkage itself is correct β this is purely a Resource problem, not a trace/parent problem:
| Check |
gh-aw spans |
gateway (mcpg) spans |
traceId |
β¦ (X) |
same (X) β
|
gateway.request.parentSpanId |
β |
= agent.setup's spanId β
|
project routing header (x-project-name) |
present |
same value β
|
resource.service.name |
gh-aw.<workflow> |
absent (empty resource) β |
So all 28 gateway.request spans + the mcp.tool_call β gateway.backend.execute branch are parented to agent.setup, in the same trace and same project β they only differ by Resource.
Impact
Because the gateway spans carry no service.name, backends that group the trace by service (and span/LLM-observability UIs in particular) place them in a separate unknown_service bucket. Their shared parent (agent.setup) lives in the gh-aw.<workflow> service bucket and is therefore "missing" from the gateway group, so the gateway spans appear as a flat set of orphan roots rather than as children of agent.setup.
Net effect for the user: instead of one connected trace, you see:
- Tree 1 β the gh-aw lifecycle spans (
pre_activation β activation β agent β detection β safe_outputs β conclusion).
- Tree 2 β a disconnected pile of
gateway.request / mcp.tool_call spans with no visible parent.
The actual tool-call telemetry (which model/tool the agent invoked) is thus detached from the run it belongs to.
Expected behavior
The gateway should emit a valid OTel Resource with at least service.name, so its spans stitch under agent.setup within the same trace. Ideally it would also carry the correlation attributes the gh-aw CLI spans already set (e.g. gh-aw.run.id, gh-aw.repository, github.run_id) so the two services correlate cleanly even in UIs that lane by service.
Suggested fix
- Resolve the OTel semconv schema-URL conflict (
1.34.0 vs 1.41.0) in gh-aw-mcpg so resource detection no longer fails (align the semconv dependency versions, or construct the Resource without the conflicting auto-detector / with an explicit schemaURL).
- Ensure the gateway always sets
service.name (e.g. mcp-gateway) even if auto-detection partially fails β a failed detector should not wipe an explicitly-provided service.name.
- Optionally propagate the gh-aw run/repo correlation attributes into the gateway Resource.
Questions
- Is the empty-Resource fallback on detector failure intended, or should an explicit
service.name survive?
- Is the
1.34.0/1.41.0 schema-URL conflict known/tracked?
I can share the redacted OTLP capture and full gateway log on request.
Note: observed in a private repository. Endpoint URLs, repo/workflow names, span IDs, and auth headers have been redacted; the gateway log line is quoted verbatim except for the endpoint host.
π€ This issue has been generated by Claude Code.
Summary
The MCP gateway (
ghcr.io/github/gh-aw-mcpg) emits its spans (gateway.request,mcp.tool_call,gateway.backend.execute) with an empty OpenTelemetry Resource β noservice.name, no attributes at all β because resource detection fails at gateway startup with a semconv schema-URL conflict. As a result, even though the gateway spans share the correcttraceIdand correctly point to theagent.setupspan as their parent, observability backends that assemble/segment the waterfall per service cannot stitch them into the gh-aw trace. The gh-aw lifecycle spans render as one tree, and the gateway spans render as a separate, parent-less group of orphan roots.Tested with gh-aw CLI
v0.79.1, engine Claude Code2.1.168,awf v0.25.68, gateway imageghcr.io/github/gh-aw-mcpg:v0.3.25.(Note: the OTLP spans report this under an attribute literally named
gh-aw.cli.version: 2.1.168, but per the run'saw_info.jsonthat2.1.168is the Claude Code engine version βcli_versionisv0.79.1. Thegh-aw.cli.versionspan attribute therefore appears to carry the engine/agent version rather than the gh-aw CLI version. Tracked separately in #38897.)Root cause: gateway resource detection fails β empty Resource
At gateway startup the OTLP tracer logs:
The gateway intends
service.name=mcp-gateway, but the schema-URL conflict (OTel semantic-conventions1.34.0vs1.41.0inside thegh-aw-mcpgbinary) discards the entire Resource, so spans are exported with no service identity.Evidence (OTLP/JSON received by a backend)
Same run, single OTLP endpoint, all spans received. Comparing the
resourceSpans[].resourceof the two span groups:Crucially, the linkage itself is correct β this is purely a Resource problem, not a trace/parent problem:
mcpg) spanstraceIdβ¦(X)gateway.request.parentSpanIdagent.setup's spanId βx-project-name)resource.service.namegh-aw.<workflow>So all 28
gateway.requestspans + themcp.tool_call β gateway.backend.executebranch are parented toagent.setup, in the same trace and same project β they only differ by Resource.Impact
Because the gateway spans carry no
service.name, backends that group the trace by service (and span/LLM-observability UIs in particular) place them in a separateunknown_servicebucket. Their shared parent (agent.setup) lives in thegh-aw.<workflow>service bucket and is therefore "missing" from the gateway group, so the gateway spans appear as a flat set of orphan roots rather than as children ofagent.setup.Net effect for the user: instead of one connected trace, you see:
pre_activation β activation β agent β detection β safe_outputs β conclusion).gateway.request/mcp.tool_callspans with no visible parent.The actual tool-call telemetry (which model/tool the agent invoked) is thus detached from the run it belongs to.
Expected behavior
The gateway should emit a valid OTel Resource with at least
service.name, so its spans stitch underagent.setupwithin the same trace. Ideally it would also carry the correlation attributes the gh-aw CLI spans already set (e.g.gh-aw.run.id,gh-aw.repository,github.run_id) so the two services correlate cleanly even in UIs that lane by service.Suggested fix
1.34.0vs1.41.0) ingh-aw-mcpgso resource detection no longer fails (align the semconv dependency versions, or construct the Resource without the conflicting auto-detector / with an explicitschemaURL).service.name(e.g.mcp-gateway) even if auto-detection partially fails β a failed detector should not wipe an explicitly-providedservice.name.Questions
service.namesurvive?1.34.0/1.41.0schema-URL conflict known/tracked?I can share the redacted OTLP capture and full gateway log on request.
Note: observed in a private repository. Endpoint URLs, repo/workflow names, span IDs, and auth headers have been redacted; the gateway log line is quoted verbatim except for the endpoint host.