spring-cloud / spring-cloud-gateway

An API Gateway built on Spring Framework and Spring Boot providing routing and more.
http://cloud.spring.io
Apache License 2.0
4.49k stars 3.3k forks source link

MVC ProxyExchange does not provide observability of URI template #3458

Open MGerriorBB opened 1 month ago

MGerriorBB commented 1 month ago

Describe the bug Using Spring Cloud 2023.0.3 and Spring Boot 3.2.7, it appears that the micrometer observability for the MVC version of ProxyExchange does not properly support URI templates. Looking at actuator at /actuator/metrics/<project>.http.client.requests the URI tag is always "none". I'm not sure if it's due to use of RestTemplate directly https://github.com/spring-cloud/spring-cloud-gateway/blob/main/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/ProxyExchange.java#L170 as opposed to RestTemplateBuilder per https://docs.spring.io/spring-framework/reference/integration/observability.html#observability.http-client.resttemplate ?

Sample Won't be able to provide the exact code, but we use UriComponentsBuilder which may be causing issues? Something like:

        return proxyExchange.uri(
            UriComponentsBuilder.fromHttpUrl("http://service.internal.com")
                .path("/v1/documents/{documentId}")
                .build(Map.of("documentId", "<documentId from PathVariable>")
        ).get();
spencergibb commented 1 month ago

I don't know if proxy exchange ever provided that.

MGerriorBB commented 1 month ago

I take back my earlier comment about using RestTemplate as opposed to RestTemplateBuilder, after doing some more digging, I believe the RestTemplateBuilder with Observability should have been injected here: https://github.com/spring-cloud/spring-cloud-gateway/blob/4a2c6d836fc8cf93afc371c06f4bdc8a6d4a0965/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/config/ProxyResponseAutoConfiguration.java#L63

Given that, I believe this could be solved by using exchange with urivariables here https://github.com/spring-cloud/spring-cloud-gateway/blob/4a2c6d836fc8cf93afc371c06f4bdc8a6d4a0965/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/ProxyExchange.java#L359 .

Does that sound like the right approach? Of course we'd need to add some setters on ProxyExchange like:

proxyExchange.uri("http://service.internal.com")
    .path("/v1/documents/{documentId}")
    .uriVariables(Map.of("documentId", "foo"))
    .get();

Is the project still actively maintained? If so I can try to open a PR, though I admit I'm not quite a spring wizard yet.