Skip to content

Commit 19588d4

Browse files
committed
Auto-detect observability beans in WebHttpHandlerBuilder
This commit ensures that both `ObservationRegsitry` and `ServerRequestObservationConvention` beans are automatically detected in the application context if they are unique. This aligns with the existing behavior for all other builder methods. Closes gh-31205
1 parent dfd631e commit 19588d4

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ public static WebHttpHandlerBuilder webHandler(WebHandler webHandler) {
162162
* ordered.
163163
* <li>{@link HttpHandlerDecoratorFactory} [0..N] -- detected by type and
164164
* ordered.
165+
* <li>{@link ObservationRegistry} -- detected by type and
166+
* configured if unique.
167+
* <li>{@link ServerRequestObservationConvention} -- detected by type and
168+
* configured if unique.
165169
* <li>{@link WebSessionManager} [0..1] -- looked up by the name
166170
* {@link #WEB_SESSION_MANAGER_BEAN_NAME}.
167171
* <li>{@link ServerCodecConfigurer} [0..1] -- looked up by the name
@@ -193,6 +197,9 @@ public static WebHttpHandlerBuilder applicationContext(ApplicationContext contex
193197
.orderedStream()
194198
.forEach(builder::httpHandlerDecorator);
195199

200+
context.getBeanProvider(ObservationRegistry.class).ifUnique(builder::observationRegistry);
201+
context.getBeanProvider(ServerRequestObservationConvention.class).ifUnique(builder::observationConvention);
202+
196203
try {
197204
builder.sessionManager(
198205
context.getBean(WEB_SESSION_MANAGER_BEAN_NAME, WebSessionManager.class));

spring-web/src/test/java/org/springframework/web/server/adapter/WebHttpHandlerBuilderTests.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,8 @@
2222
import java.util.function.BiFunction;
2323
import java.util.function.Function;
2424

25+
import io.micrometer.observation.tck.TestObservationRegistry;
26+
import io.micrometer.observation.tck.TestObservationRegistryAssert;
2527
import org.junit.jupiter.api.Test;
2628
import reactor.core.publisher.Flux;
2729
import reactor.core.publisher.Mono;
@@ -36,6 +38,8 @@
3638
import org.springframework.http.server.reactive.HttpHandler;
3739
import org.springframework.http.server.reactive.HttpHandlerDecoratorFactory;
3840
import org.springframework.http.server.reactive.ServerHttpRequest;
41+
import org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention;
42+
import org.springframework.http.server.reactive.observation.ServerRequestObservationConvention;
3943
import org.springframework.web.server.ServerWebExchange;
4044
import org.springframework.web.server.WebExceptionHandler;
4145
import org.springframework.web.server.WebFilter;
@@ -50,6 +54,7 @@
5054
* Unit tests for {@link WebHttpHandlerBuilder}.
5155
*
5256
* @author Rossen Stoyanchev
57+
* @author Brian Clozel
5358
*/
5459
public class WebHttpHandlerBuilderTests {
5560

@@ -155,6 +160,19 @@ void httpHandlerDecoratorFactoryBeans() {
155160
assertThat(headerValue.apply("decoratorC")).isLessThan(headerValue.apply("decoratorB"));
156161
}
157162

163+
@Test
164+
void observationRegistry() {
165+
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ObservationConfig.class);
166+
HttpHandler handler = WebHttpHandlerBuilder.applicationContext(applicationContext).build();
167+
168+
MockServerHttpResponse response = new MockServerHttpResponse();
169+
handler.handle(MockServerHttpRequest.get("/").build(), response).block();
170+
171+
TestObservationRegistry observationRegistry = applicationContext.getBean(TestObservationRegistry.class);
172+
TestObservationRegistryAssert.assertThat(observationRegistry).hasObservationWithNameEqualTo("http.server.requests")
173+
.that().hasLowCardinalityKeyValue("uri", "UNKNOWN");
174+
}
175+
158176
private static Mono<Void> writeToResponse(ServerWebExchange exchange, String value) {
159177
byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
160178
DataBuffer buffer = DefaultDataBufferFactory.sharedInstance.wrap(bytes);
@@ -277,4 +295,24 @@ public WebHandler webHandler() {
277295
}
278296
}
279297

298+
@Configuration
299+
static class ObservationConfig {
300+
301+
@Bean
302+
public TestObservationRegistry testObservationRegistry() {
303+
return TestObservationRegistry.create();
304+
}
305+
306+
@Bean
307+
public ServerRequestObservationConvention requestObservationConvention() {
308+
return new DefaultServerRequestObservationConvention();
309+
}
310+
311+
@Bean
312+
public WebHandler webHandler() {
313+
return exchange -> exchange.getResponse().setComplete();
314+
}
315+
316+
}
317+
280318
}

0 commit comments

Comments
 (0)