As part of #29334, the HTTP observability types were moved from org.springframework.web.observation
to org.springframework.http.observation
. While this improved the overall structure of the codebase, it also introduced a package tangle since classes in org.springframework.http.observation.reactive
depend on org.springframework.web.*
types like PathPattern
and ServerWebExchange
.
We should either ensure that observation types don't depend on higher level types (by flattening the ServerWebExchange
dependency and using raw String
instead of path pattern), or move back types where they were.
As part of this issue, we should ensure that no cycle remains and that the package structure is consistent, including in client observations.
Comment From: bclozel
Removing the ServerWebExchange
and PathPattern
dependency from the reactive instrumentation seems straightforward enough and aligns well with the Servlet variant. Moving the server instrumentation to different packages also brings a clearer structure.
We can consider the following changes.
Servlet HTTP server instrumentation:
* lives in org.springframework.http.server.observation
* depends on io.micrometer.*
and org.springframework.http.*
and jakarta.servlet.http.*
types
* is used by the ServerHttpObservationFilter
in org.springframework.web.filter
Reactive HTTP server instrumentation:
* lives in org.springframework.http.server.reactive.observation
* depends on io.micrometer.*
and org.springframework.http.*
and org.springframework.http.server.reactive.*
types
* is used by the ServerHttpObservationFilter
in org.springframework.web.filter.reactive
We could also keep all server instrumentation under org.springframework.http.server.observation
but this would mean maintaining an observation.reactive
sub-package. While this has been a common pattern so far, we don't need to nest reactive variants under a parent package, especially for new features and deeply nested packages. In this case, observation
and observation.reactive
share no common types and only depend on the corresponding HTTP API.
On the client side, we'll leave things as is, since the current situation looks right:
HTTP client instrumentation:
* lives in org.springframework.http.client.observation
* depends on io.micrometer.*
and org.springframework.http.client.*
types
* is used by org.springframework.web.client.RestTemplate
Reactive HTTP client instrumentation:
* lives in org.springframework.web.reactive.function.client
because moving it to org.springframework.web.reactive.function.client.observation
would create a cycle between both packages
* unlike other instrumentations, we cannot use org.springframework.http.client.reactive.*
types for building the instrumentation. Instead of instrumenting the WebClient
directly, we would need to move the instrumentation to wrap the ClientHttpConnector
, but we would still be in org.springframework.web.reactive.function.client.ExchangeFunctions
. Also, the instrumentation needs to mutate the client request before writing it out (for propagating headers) and this introduces additional complexity with ClientHttpRequest
* depends on io.micrometer.*
and org.springframework.web.reactive.function.client.*
types
* is used by org.springframework.web.reactive.function.client.WebClient