Skip to content

otel: suppress /livez and /readyz spans, fix tools/call span name#44

Merged
emsearcy merged 2 commits intomainfrom
arch-374-suppress-health-check-spans
Mar 27, 2026
Merged

otel: suppress /livez and /readyz spans, fix tools/call span name#44
emsearcy merged 2 commits intomainfrom
arch-374-suppress-health-check-spans

Conversation

@emsearcy
Copy link
Copy Markdown
Contributor

@emsearcy emsearcy commented Mar 26, 2026

Summary

Two related observability improvements to the OTel instrumentation.

ARCH-374 — Suppress health-check probe spans

Kubernetes health-check probes (/livez, /readyz) are called at high
frequency and generate noisy, low-value spans in the tracing backend.
An otelhttp.WithFilter predicate is added to exclude those two paths
from trace creation entirely.

Bonus — Fix tools/call span name

The MCP semconv spec recommends span names in the format:

{mcp.method.name} {target}

where target should match gen_ai.tool.name when applicable.
Previously all tools/call invocations shared the same span name
("tools/call"), meaning Datadog flame charts required expanding
attributes to see which tool was actually called.

mcpOTelMiddleware now sets the span name to
"tools/call <tool_name>" (e.g. "tools/call search_projects"),
making flame charts immediately readable.

Ref: https://opentelemetry.io/docs/specs/semconv/gen-ai/mcp/#server


Jira: ARCH-374

Health-check probe endpoints (/livez, /readyz) are called at high
frequency by Kubernetes and generate noisy, low-value spans in the
tracing backend. Add an otelhttp.WithFilter predicate to exclude those
two paths from trace creation.

Also update mcpOTelMiddleware to name MCP spans following the semconv
recommendation:

  {mcp.method.name} {target}

where target is gen_ai.tool.name when available. For tools/call this
means spans are now named e.g. "tools/call search_projects" instead of
just "tools/call", making Datadog flame charts immediately readable
without having to expand span attributes.

Ref: https://opentelemetry.io/docs/specs/semconv/gen-ai/mcp/#server

🤖 Generated with [GitHub Copilot](https://github.com/features/copilot) (via Zed)

Signed-off-by: Eric Searcy <eric@linuxfoundation.org>
Copilot AI review requested due to automatic review settings March 26, 2026 22:02
Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Improves OpenTelemetry instrumentation in the MCP server by reducing trace noise from Kubernetes health probes and making tools/call spans more informative/readable in tracing backends.

Changes:

  • Suppress tracing for high-frequency /livez and /readyz HTTP endpoints via otelhttp.WithFilter.
  • Update MCP middleware span naming for tools/call to include the tool name (e.g., tools/call search_projects) per MCP semconv guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +353 to +358
spanName := method
if method == "tools/call" {
if params, ok := req.GetParams().(*mcp.CallToolParamsRaw); ok && params.Name != "" {
spanName = method + " " + params.Name
}
}
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

The tool name is extracted from req.GetParams() here and then extracted again later when setting gen_ai.tool.name. Consider extracting params/toolName once inside the method == "tools/call" branch and reusing it for both the span name and span attributes to avoid duplicated type assertions and keep the logic in sync.

Suggested change
spanName := method
if method == "tools/call" {
if params, ok := req.GetParams().(*mcp.CallToolParamsRaw); ok && params.Name != "" {
spanName = method + " " + params.Name
}
}
toolName := ""
if method == "tools/call" {
if params, ok := req.GetParams().(*mcp.CallToolParamsRaw); ok && params.Name != "" {
toolName = params.Name
}
}
spanName := method
if toolName != "" {
spanName = method + " " + toolName
}

Copilot uses AI. Check for mistakes.
@emsearcy emsearcy merged commit add8afd into main Mar 27, 2026
5 checks passed
@emsearcy emsearcy deleted the arch-374-suppress-health-check-spans branch March 27, 2026 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants