Skip to content

Commit 28f9f20

Browse files
committed
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
1 parent fcf1207 commit 28f9f20

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/reactive/WebFluxObservationAutoConfiguration.java

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.springframework.boot.context.properties.EnableConfigurationProperties;
4343
import org.springframework.context.annotation.Bean;
4444
import org.springframework.context.annotation.Configuration;
45+
import org.springframework.core.Ordered;
4546
import org.springframework.core.annotation.Order;
4647
import org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention;
4748
import org.springframework.http.server.reactive.observation.ServerRequestObservationConvention;
@@ -77,6 +78,7 @@ public WebFluxObservationAutoConfiguration(MetricsProperties metricsProperties,
7778

7879
@Bean
7980
@ConditionalOnMissingBean
81+
@Order(Ordered.HIGHEST_PRECEDENCE + 1)
8082
public ServerHttpObservationFilter webfluxObservationFilter(ObservationRegistry registry,
8183
ObjectProvider<ServerRequestObservationConvention> customConvention,
8284
ObjectProvider<WebFluxTagsProvider> tagConfigurer,

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/observation/web/reactive/WebFluxObservationAutoConfigurationTests.java

+37
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.observation.web.reactive;
1818

19+
import java.util.List;
20+
1921
import io.micrometer.core.instrument.MeterRegistry;
2022
import io.micrometer.core.instrument.Tag;
2123
import io.micrometer.core.instrument.Tags;
2224
import org.junit.jupiter.api.Test;
2325
import org.junit.jupiter.api.extension.ExtendWith;
26+
import reactor.core.publisher.Mono;
2427

2528
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
2629
import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun;
@@ -37,10 +40,14 @@
3740
import org.springframework.boot.test.system.OutputCaptureExtension;
3841
import org.springframework.context.annotation.Bean;
3942
import org.springframework.context.annotation.Configuration;
43+
import org.springframework.core.Ordered;
44+
import org.springframework.core.annotation.Order;
4045
import org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention;
4146
import org.springframework.test.web.reactive.server.WebTestClient;
4247
import org.springframework.web.filter.reactive.ServerHttpObservationFilter;
4348
import org.springframework.web.server.ServerWebExchange;
49+
import org.springframework.web.server.WebFilter;
50+
import org.springframework.web.server.WebFilterChain;
4451

4552
import static org.assertj.core.api.Assertions.assertThat;
4653

@@ -64,6 +71,16 @@ void shouldProvideWebFluxObservationFilter() {
6471
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ServerHttpObservationFilter.class));
6572
}
6673

74+
@Test
75+
void shouldProvideWebFluxObservationFilterOrdered() {
76+
this.contextRunner.withBean(FirstWebFilter.class).withBean(ThirdWebFilter.class).run((context) -> {
77+
List<WebFilter> webFilters = context.getBeanProvider(WebFilter.class).orderedStream().toList();
78+
assertThat(webFilters.get(0)).isInstanceOf(FirstWebFilter.class);
79+
assertThat(webFilters.get(1)).isInstanceOf(ServerHttpObservationFilter.class);
80+
assertThat(webFilters.get(2)).isInstanceOf(ThirdWebFilter.class);
81+
});
82+
}
83+
6784
@Test
6885
void shouldUseConventionAdapterWhenCustomTagsProvider() {
6986
this.contextRunner.withUserConfiguration(CustomTagsProviderConfiguration.class).run((context) -> {
@@ -207,4 +224,24 @@ static class CustomConvention extends DefaultServerRequestObservationConvention
207224

208225
}
209226

227+
@Order(Ordered.HIGHEST_PRECEDENCE)
228+
static class FirstWebFilter implements WebFilter {
229+
230+
@Override
231+
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
232+
return chain.filter(exchange);
233+
}
234+
235+
}
236+
237+
@Order(Ordered.HIGHEST_PRECEDENCE + 2)
238+
static class ThirdWebFilter implements WebFilter {
239+
240+
@Override
241+
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
242+
return chain.filter(exchange);
243+
}
244+
245+
}
246+
210247
}

spring-boot-project/spring-boot-docs/src/docs/asciidoc/web/reactive.adoc

+3
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ When it does so, the orders shown in the following table will be used:
207207
|===
208208
| Web Filter | Order
209209

210+
| `ServerHttpObservationFilter` (Micrometer Observability)
211+
| `Ordered.HIGHEST_PRECEDENCE + 1`
212+
210213
| `WebFilterChainProxy` (Spring Security)
211214
| `-100`
212215

0 commit comments

Comments
 (0)