diff --git a/spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java b/spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java index 30430f40e0..08a914f635 100644 --- a/spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java +++ b/spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java @@ -162,6 +162,10 @@ public final class WebHttpHandlerBuilder { * ordered. *
  • {@link HttpHandlerDecoratorFactory} [0..N] -- detected by type and * ordered. + *
  • {@link ObservationRegistry} -- detected by type and + * configured if unique. + *
  • {@link ServerRequestObservationConvention} -- detected by type and + * configured if unique. *
  • {@link WebSessionManager} [0..1] -- looked up by the name * {@link #WEB_SESSION_MANAGER_BEAN_NAME}. *
  • {@link ServerCodecConfigurer} [0..1] -- looked up by the name @@ -193,6 +197,9 @@ public final class WebHttpHandlerBuilder { .orderedStream() .forEach(builder::httpHandlerDecorator); + context.getBeanProvider(ObservationRegistry.class).ifUnique(builder::observationRegistry); + context.getBeanProvider(ServerRequestObservationConvention.class).ifUnique(builder::observationConvention); + try { builder.sessionManager( context.getBean(WEB_SESSION_MANAGER_BEAN_NAME, WebSessionManager.class)); diff --git a/spring-web/src/test/java/org/springframework/web/server/adapter/WebHttpHandlerBuilderTests.java b/spring-web/src/test/java/org/springframework/web/server/adapter/WebHttpHandlerBuilderTests.java index a5c36cf842..522d8aafb1 100644 --- a/spring-web/src/test/java/org/springframework/web/server/adapter/WebHttpHandlerBuilderTests.java +++ b/spring-web/src/test/java/org/springframework/web/server/adapter/WebHttpHandlerBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BiFunction; import java.util.function.Function; +import io.micrometer.observation.tck.TestObservationRegistry; +import io.micrometer.observation.tck.TestObservationRegistryAssert; import org.junit.jupiter.api.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -36,6 +38,8 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.http.server.reactive.HttpHandlerDecoratorFactory; import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention; +import org.springframework.http.server.reactive.observation.ServerRequestObservationConvention; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebExceptionHandler; import org.springframework.web.server.WebFilter; @@ -50,6 +54,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Unit tests for {@link WebHttpHandlerBuilder}. * * @author Rossen Stoyanchev + * @author Brian Clozel */ public class WebHttpHandlerBuilderTests { @@ -155,6 +160,19 @@ public class WebHttpHandlerBuilderTests { assertThat(headerValue.apply("decoratorC")).isLessThan(headerValue.apply("decoratorB")); } + @Test + void observationRegistry() { + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ObservationConfig.class); + HttpHandler handler = WebHttpHandlerBuilder.applicationContext(applicationContext).build(); + + MockServerHttpResponse response = new MockServerHttpResponse(); + handler.handle(MockServerHttpRequest.get("/").build(), response).block(); + + TestObservationRegistry observationRegistry = applicationContext.getBean(TestObservationRegistry.class); + TestObservationRegistryAssert.assertThat(observationRegistry).hasObservationWithNameEqualTo("http.server.requests") + .that().hasLowCardinalityKeyValue("uri", "UNKNOWN"); + } + private static Mono writeToResponse(ServerWebExchange exchange, String value) { byte[] bytes = value.getBytes(StandardCharsets.UTF_8); DataBuffer buffer = DefaultDataBufferFactory.sharedInstance.wrap(bytes); @@ -277,4 +295,24 @@ public class WebHttpHandlerBuilderTests { } } + @Configuration + static class ObservationConfig { + + @Bean + public TestObservationRegistry testObservationRegistry() { + return TestObservationRegistry.create(); + } + + @Bean + public ServerRequestObservationConvention requestObservationConvention() { + return new DefaultServerRequestObservationConvention(); + } + + @Bean + public WebHandler webHandler() { + return exchange -> exchange.getResponse().setComplete(); + } + + } + }