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