Skip to content

DefaultAdvisorObservationConvention produces a span name with stray spaces #6750

Description

@kycasdzxc

Bug description

The span produced for ToolCallingAdvisor is named tool _calling : there is a
space before _calling and a trailing space at the end. Tool calling is on by
default, so this appears in every trace where the model calls a tool.

Environment

Spring AI 2.0.0, Spring Boot 4.1.0, Java 21. Anthropic chat model with tool
callbacks supplied by an MCP client. Traces exported over OTLP to the
OpenTelemetry Collector. The same code is present on main.

Steps to reproduce

  1. Build a ChatClient with tool callbacks and tracing to an OTLP endpoint.
  2. Send a prompt that makes the model call a tool.
  3. Read the span names.

From the Collector's debug exporter, piped through cat -A so that $ marks
end of line:

Name           : tool _calling $
Name           : spring_ai chat_client$
Name           : call$

Expected behavior

A span name with no embedded or trailing whitespace, for example tool_calling.

Minimal Complete Reproducible example

https://github.com/kycasdzxc/spring-ai-otel-example

docker compose up -d, run the app, then ask a question that triggers a tool
call. The malformed name appears in the collector output and in Tempo.

The minimal condition is narrower than that project: any advisor whose
getName() returns a string containing spaces reproduces it. ToolCallingAdvisor
is built in, so no custom advisor is needed.

Root cause

DefaultAdvisorObservationConvention#getContextualName:

return ParsingUtils.reConcatenateCamelCase(context.getAdvisorName(), "_")
    .replace("_around_advisor", "")
    .replace("_advisor", "");

reConcatenateCamelCase splits on camelCase boundaries, so it expects an
identifier such as ToolCallingAdvisor. ToolCallingAdvisor#getName() returns
the display form "Tool Calling Advisor", and splitting that leaves the original
spaces attached to each token:

"Tool Calling Advisor"
  -> ["Tool ", "Calling ", "Advisor"]
  -> "tool _calling _advisor"
  -> replace("_advisor", "") -> "tool _calling "

Advisors whose name contains no spaces are unaffected: call stays call.

Either normalising whitespace in getContextualName or having advisors supply an
identifier-shaped name would fix it.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions