Skip to content

Rename span attributes to MCP OTEL semantic conventions - #3748

Merged
ChrisJBurns merged 3 commits into
mainfrom
otel/pr2a-attribute-rename-v2
Feb 10, 2026
Merged

ChrisJBurns merged 3 commits into
mainfrom
otel/pr2a-attribute-rename-v2

Conversation

@ChrisJBurns

@ChrisJBurns ChrisJBurns commented Feb 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds new standard OTEL semantic convention attribute names alongside the gated legacy names
  • New attributes are always emitted; legacy names are conditionally emitted behind UseLegacyAttributes (from Gate legacy span attributes behind UseLegacyAttributes flag #3747)
  • Adds mapTransport helper to convert MCP transport types to OTEL network.transport values
  • Updates span naming: mcp.tools/calltools/call (method only, no resource target to avoid cardinality issues)
  • Renames rpc.system to rpc.system.name (per OTEL deprecation), moves rpc.system to legacy block
  • Emits network.protocol.name and network.protocol.version in SSE connection spans

Key attribute renames (new names always emitted, old names gated):

Old (legacy) New (standard)
http.method http.request.method
http.url url.full
http.status_code http.response.status_code
mcp.method mcp.method.name
mcp.request.id jsonrpc.request.id
mcp.tool.name gen_ai.tool.name
mcp.tool.arguments gen_ai.tool.call.arguments
mcp.transport network.transport
mcp.resource.id mcp.resource.uri
rpc.system rpc.system.name

New attributes with no legacy equivalent:

  • jsonrpc.protocol.version
  • gen_ai.operation.name, gen_ai.prompt.name
  • network.protocol.name, url.scheme, url.path, url.query
  • server.address, user_agent.original
  • http.request.body.size, http.response.body.size

Transport mapping:

Transport network.transport
stdio pipe
sse tcp
streamable-http tcp

Stacked on #3747 (gates legacy attributes behind the flag).

Test plan

  • Unit tests for dual emission (legacy enabled: both old and new present; legacy disabled: only new present)
  • Unit tests for mapTransport helper
  • Unit tests for createSpanName format (method only, no resource ID)
  • Unit tests for mcp.resource.uri conditional logic (present for resources/read, absent for tools/call)
  • Unit tests for span status verification (codes.Ok for 2xx, codes.Error for 5xx)
  • Integration test verifies both old and new attribute names present
  • task lint passes
  • task test passes

🤖 Generated with Claude Code

@codecov

codecov Bot commented Feb 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.05556% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.33%. Comparing base (b9af6fc) to head (81cde82).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/telemetry/middleware.go 93.05% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3748      +/-   ##
==========================================
- Coverage   66.35%   66.33%   -0.03%     
==========================================
  Files         427      427              
  Lines       41807    41864      +57     
==========================================
+ Hits        27741    27770      +29     
- Misses      11953    11982      +29     
+ Partials     2113     2112       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Base automatically changed from otel/pr2a-feature-flag-legacy to main February 10, 2026 15:52
Add new standard OTEL semantic convention attribute names alongside
the existing legacy names. New attributes (http.request.method,
mcp.method.name, gen_ai.tool.name, etc.) are always emitted, while
legacy names are conditionally emitted behind UseLegacyAttributes.

Also updates createSpanName to use "{method} {resourceID}" format
and adds mapTransport helper for network.transport mapping.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ChrisJBurns
ChrisJBurns force-pushed the otel/pr2a-attribute-rename-v2 branch from e0d5fd6 to aed1ec5 Compare February 10, 2026 15:54
@github-actions github-actions Bot added size/M Medium PR: 300-599 lines changed and removed size/M Medium PR: 300-599 lines changed labels Feb 10, 2026
- Remove duplicate mcp.resource.uri emission for resources/read
- Rename rpc.system to rpc.system.name, move rpc.system to legacy block
- Capture network.protocol.name and network.protocol.version in SSE path
- Simplify span names to just MCP method (avoid cardinality risk)
- Add network.protocol.version to mapTransport (SSE=1.1, streamable-http=2)
- Fix mockSpan.SetStatus to capture status for test verification
- Delete dead TestHTTPMiddleware_FinalizeSpan_Logic test
- Add tests for mcp.resource.uri conditional logic and protocol version

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot added size/M Medium PR: 300-599 lines changed and removed size/M Medium PR: 300-599 lines changed labels Feb 10, 2026
Defer mcp.protocol.version to a follow-up once we determine the
correct source (header vs constant vs SDK).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot added size/M Medium PR: 300-599 lines changed and removed size/M Medium PR: 300-599 lines changed labels Feb 10, 2026
@ChrisJBurns
ChrisJBurns merged commit e15caa0 into main Feb 10, 2026
36 checks passed
@ChrisJBurns
ChrisJBurns deleted the otel/pr2a-attribute-rename-v2 branch February 10, 2026 17:26

// New OTEL MCP semantic convention attributes (always emitted)
span.SetAttributes(
attribute.String("mcp.method.name", parsedMCP.Method),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If someone like me has no idea where these come from: https://opentelemetry.io/docs/specs/semconv/gen-ai/mcp/

case "sse":
return networkTransportTCP, networkProtocolHTTP, "1.1"
case "streamable-http":
return networkTransportTCP, networkProtocolHTTP, "2"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it always http/2 for streamable http or "usually" ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M Medium PR: 300-599 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants