In 2 tests, one using restTemplate and the other webClient, the tracing attribute http.route has differing values.

        var restTemplate = restTemplateBuilder.rootUri("http://localhost:" + port).build();
        var response = restTemplate.getForEntity("/foo/{foo-id}?query=true", String.class, "bar");

       // assert that org.springframework.http.client.observation.ClientRequestObservationContext.getUriTemplate() is http://localhost:1234/foo/{foo-id}

ClientRequestObservationContext

        var webClient = webClientBuilder.baseUrl("http://localhost:" + port).build();
        StepVerifier.create(webClient
                .get().uri("/foo/{foo-id}?query=true", "bar").attributes()
                .retrieve()
                .bodyToMono(String.class))
                .expectNext("bar?query=true")
                .verifyComplete();

       // assert that org.springframework.web.reactive.function.client.ClientRequestObservationContext.getUriTemplate() is /foo/{foo-id}

This not only requires multiple test paths (webmvc leads to a different value than webflux), but also leads to an inconsistent experience when using tracing data (raw data, or using a UI). When using tracing data, one now has to consider if webClient or restTemplate was used, which may be unreasonable if not familiar with the relevant application(s).

Comment From: bclozel

Spring framework 6.3.x does not exist. Can you elaborate in which version this behavior appeared and how it was behaving before?

Comment From: wleese

@bclozel oh sorry, I've changed the title. We originally reported a similar issue in https://github.com/spring-projects/spring-framework/issues/31882 and https://github.com/spring-projects/spring-framework/issues/32003.

All these issues relate to the same test on our side. In the 2 issues I linked, we failed to mention that this inconsistency between restTemplate and webClient makes things awkward, so that is what this issue is about.

Also updated the original post to reflect exactly what we're asserting.

Comment From: bclozel

Hello @wleese

I had another look to this issue and unfortunately I don't think we can change this. You're right that this change of behavior is due to #31882 and #32003 and I think they're valid. On the other hand, the same feature in RestTemplate is not implemented in Spring Framework but in Spring Boot.

In Spring Framework, WebClient has its own Builder interface with a base URI support. #31882 and #32003 refined this behavior because of community reports.

In Spring Framework, RestTemplate has no builder and no notion of base URI. This is implemented in Spring Boot with RestTemplateBuilder and predates WebClient and the observability support. The base URI support is using a UriTemplateHandler contract to support that. This handler delegates to the actual uri template handler for expansion and prepends the base URI if necessary. See https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RestTemplateBuilder.java#L642 and https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RootUriTemplateHandler.java#L69.

Unfortunately, this base URI information is lost during the expansion and it's too late to get it for the RestTemplate instrumentation to get it. The only proper solution here would be to introduce a builder directly in Spring Framework and align the behavior here. Feel free to create an issue for that in Spring Framework, but you should know that if we do so, deprecating Spring Boot's ResTemplateBuilder and retiring it would require a transition period that would be quite long.

If consistency is very important for you in the short term, you can use a custom ObservationFilter that processes the http.route keyvalue and removes the host part to revert this behavior.

I'm closing this issue now as I don't see any way to fix this without causing other, more important regressions.

Comment From: wleese

Thanks for the elaborate explanation. We'll make it consistent on our end.