Declare order for ServerHttpObservationFilter WebFilter

This commit declares an `@Order` for the `ServerHttpObservationFilter`
bean declaration in the Observation WebFlux auto-configuration.

This allows developers to consistently order other `WebFilter` instances
relatively to this one. Here, `@Order(Ordered.HIGHEST_PRECEDENCE + 1)`
has been chosen to align with the order of its MVC counterpart.

Fixes gh-33444
This commit is contained in:
Brian Clozel 2022-12-19 18:24:36 +01:00
parent fcf120783a
commit 28f9f20d39
3 changed files with 42 additions and 0 deletions

View File

@ -42,6 +42,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention;
import org.springframework.http.server.reactive.observation.ServerRequestObservationConvention;
@ -77,6 +78,7 @@ public class WebFluxObservationAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@Order(Ordered.HIGHEST_PRECEDENCE + 1)
public ServerHttpObservationFilter webfluxObservationFilter(ObservationRegistry registry,
ObjectProvider<ServerRequestObservationConvention> customConvention,
ObjectProvider<WebFluxTagsProvider> tagConfigurer,

View File

@ -16,11 +16,14 @@
package org.springframework.boot.actuate.autoconfigure.observation.web.reactive;
import java.util.List;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import reactor.core.publisher.Mono;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun;
@ -37,10 +40,14 @@ import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.filter.reactive.ServerHttpObservationFilter;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import static org.assertj.core.api.Assertions.assertThat;
@ -64,6 +71,16 @@ class WebFluxObservationAutoConfigurationTests {
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ServerHttpObservationFilter.class));
}
@Test
void shouldProvideWebFluxObservationFilterOrdered() {
this.contextRunner.withBean(FirstWebFilter.class).withBean(ThirdWebFilter.class).run((context) -> {
List<WebFilter> webFilters = context.getBeanProvider(WebFilter.class).orderedStream().toList();
assertThat(webFilters.get(0)).isInstanceOf(FirstWebFilter.class);
assertThat(webFilters.get(1)).isInstanceOf(ServerHttpObservationFilter.class);
assertThat(webFilters.get(2)).isInstanceOf(ThirdWebFilter.class);
});
}
@Test
void shouldUseConventionAdapterWhenCustomTagsProvider() {
this.contextRunner.withUserConfiguration(CustomTagsProviderConfiguration.class).run((context) -> {
@ -207,4 +224,24 @@ class WebFluxObservationAutoConfigurationTests {
}
@Order(Ordered.HIGHEST_PRECEDENCE)
static class FirstWebFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange);
}
}
@Order(Ordered.HIGHEST_PRECEDENCE + 2)
static class ThirdWebFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange);
}
}
}

View File

@ -207,6 +207,9 @@ When it does so, the orders shown in the following table will be used:
|===
| Web Filter | Order
| `ServerHttpObservationFilter` (Micrometer Observability)
| `Ordered.HIGHEST_PRECEDENCE + 1`
| `WebFilterChainProxy` (Spring Security)
| `-100`