@ -16,12 +16,12 @@
package org.springframework.boot.actuate.autoconfigure.observation.web.reactive ;
package org.springframework.boot.actuate.autoconfigure.observation.web.reactive ;
import java.util.List ;
import java.time.Duration ;
import java.time.temporal.ChronoUnit ;
import io.micrometer.core.instrument.MeterRegistry ;
import io.micrometer.core.instrument.MeterRegistry ;
import org.junit.jupiter.api.Test ;
import org.junit.jupiter.api.Test ;
import org.junit.jupiter.api.extension.ExtendWith ;
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.MetricsAutoConfiguration ;
import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun ;
import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun ;
@ -33,16 +33,6 @@ import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplic
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner ;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner ;
import org.springframework.boot.test.system.CapturedOutput ;
import org.springframework.boot.test.system.CapturedOutput ;
import org.springframework.boot.test.system.OutputCaptureExtension ;
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 ;
import static org.assertj.core.api.Assertions.assertThat ;
@ -54,7 +44,6 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Madhura Bhave
* @author Madhura Bhave
* /
* /
@ExtendWith ( OutputCaptureExtension . class )
@ExtendWith ( OutputCaptureExtension . class )
@SuppressWarnings ( "removal" )
class WebFluxObservationAutoConfigurationTests {
class WebFluxObservationAutoConfigurationTests {
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner ( )
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner ( )
@ -62,31 +51,6 @@ class WebFluxObservationAutoConfigurationTests {
. withConfiguration (
. withConfiguration (
AutoConfigurations . of ( ObservationAutoConfiguration . class , WebFluxObservationAutoConfiguration . class ) ) ;
AutoConfigurations . of ( ObservationAutoConfiguration . class , WebFluxObservationAutoConfiguration . class ) ) ;
@Test
void shouldProvideWebFluxObservationFilter ( ) {
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 shouldUseCustomConventionWhenAvailable ( ) {
this . contextRunner . withUserConfiguration ( CustomConventionConfiguration . class ) . run ( ( context ) - > {
assertThat ( context ) . hasSingleBean ( ServerHttpObservationFilter . class ) ;
assertThat ( context ) . getBean ( ServerHttpObservationFilter . class )
. extracting ( "observationConvention" )
. isInstanceOf ( CustomConvention . class ) ;
} ) ;
}
@Test
@Test
void afterMaxUrisReachedFurtherUrisAreDenied ( CapturedOutput output ) {
void afterMaxUrisReachedFurtherUrisAreDenied ( CapturedOutput output ) {
this . contextRunner . withUserConfiguration ( TestController . class )
this . contextRunner . withUserConfiguration ( TestController . class )
@ -108,7 +72,7 @@ class WebFluxObservationAutoConfigurationTests {
. withPropertyValues ( "management.metrics.web.server.max-uri-tags=2" ,
. withPropertyValues ( "management.metrics.web.server.max-uri-tags=2" ,
"management.observations.http.server.requests.name=my.http.server.requests" )
"management.observations.http.server.requests.name=my.http.server.requests" )
. run ( ( context ) - > {
. run ( ( context ) - > {
MeterRegistry registry = getInitializedMeterRegistry ( context );
MeterRegistry registry = getInitializedMeterRegistry ( context , "my.http.server.requests" );
assertThat ( registry . get ( "my.http.server.requests" ) . meters ( ) ) . hasSizeLessThanOrEqualTo ( 2 ) ;
assertThat ( registry . get ( "my.http.server.requests" ) . meters ( ) ) . hasSizeLessThanOrEqualTo ( 2 ) ;
assertThat ( output ) . contains ( "Reached the maximum number of URI tags for 'my.http.server.requests'" ) ;
assertThat ( output ) . contains ( "Reached the maximum number of URI tags for 'my.http.server.requests'" ) ;
} ) ;
} ) ;
@ -127,53 +91,17 @@ class WebFluxObservationAutoConfigurationTests {
} ) ;
} ) ;
}
}
private MeterRegistry getInitializedMeterRegistry ( AssertableReactiveWebApplicationContext context )
private MeterRegistry getInitializedMeterRegistry ( AssertableReactiveWebApplicationContext context ) {
throws Exception {
return getInitializedMeterRegistry ( context , "http.server.requests" ) ;
return getInitializedMeterRegistry ( context , "/test0" , "/test1" , "/test2" ) ;
}
}
private MeterRegistry getInitializedMeterRegistry ( AssertableReactiveWebApplicationContext context , String . . . urls )
private MeterRegistry getInitializedMeterRegistry ( AssertableReactiveWebApplicationContext context ,
throws Exception {
String metricName ) {
assertThat ( context ) . hasSingleBean ( ServerHttpObservationFilter . class ) ;
MeterRegistry meterRegistry = context . getBean ( MeterRegistry . class ) ;
WebTestClient client = WebTestClient . bindToApplicationContext ( context ) . build ( ) ;
meterRegistry . timer ( metricName , "uri" , "/test0" ) . record ( Duration . of ( 500 , ChronoUnit . SECONDS ) ) ;
for ( String url : urls ) {
meterRegistry . timer ( metricName , "uri" , "/test1" ) . record ( Duration . of ( 500 , ChronoUnit . SECONDS ) ) ;
client . get ( ) . uri ( url ) . exchange ( ) . expectStatus ( ) . isOk ( ) ;
meterRegistry . timer ( metricName , "uri" , "/test2" ) . record ( Duration . of ( 500 , ChronoUnit . SECONDS ) ) ;
}
return meterRegistry ;
return context . getBean ( MeterRegistry . class ) ;
}
@Configuration ( proxyBeanMethods = false )
static class CustomConventionConfiguration {
@Bean
CustomConvention customConvention ( ) {
return new CustomConvention ( ) ;
}
}
static class CustomConvention extends DefaultServerRequestObservationConvention {
}
@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 ) ;
}
}
}
}
}