Merge pull request #32973 from izeye

* gh-32973:
  Polish "Handle custom observation name for HTTP reqs in max URI tag filters"
  Handle custom observation name for HTTP reqs in max URI tag filters

Closes gh-32973
pull/32994/head
Andy Wilkinson 2 years ago
commit bdc960da4e

@ -27,7 +27,6 @@ import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties.Web.Server;
import org.springframework.boot.actuate.autoconfigure.metrics.OnlyOnceLoggingDenyMeterFilter;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration;
@ -108,12 +107,15 @@ public class WebFluxObservationAutoConfiguration {
@Bean
@Order(0)
MeterFilter metricsHttpServerUriTagFilter(MetricsProperties properties) {
Server serverProperties = properties.getWeb().getServer();
String metricName = serverProperties.getRequest().getMetricName();
MeterFilter metricsHttpServerUriTagFilter(MetricsProperties metricsProperties,
ObservationProperties observationProperties) {
String observationName = observationProperties.getHttp().getServer().getRequests().getName();
String name = (observationName != null) ? observationName
: metricsProperties.getWeb().getServer().getRequest().getMetricName();
MeterFilter filter = new OnlyOnceLoggingDenyMeterFilter(
() -> "Reached the maximum number of URI tags for '%s'.".formatted(metricName));
return MeterFilter.maximumAllowableTags(metricName, "uri", serverProperties.getMaxUriTags(), filter);
() -> "Reached the maximum number of URI tags for '%s'.".formatted(name));
return MeterFilter.maximumAllowableTags(name, "uri", metricsProperties.getWeb().getServer().getMaxUriTags(),
filter);
}
}

@ -84,10 +84,7 @@ public class WebMvcObservationAutoConfiguration {
public FilterRegistrationBean<ServerHttpObservationFilter> webMvcObservationFilter(ObservationRegistry registry,
ObjectProvider<WebMvcTagsProvider> customTagsProvider,
ObjectProvider<WebMvcTagsContributor> contributorsProvider) {
String observationName = this.observationProperties.getHttp().getServer().getRequests().getName();
String metricName = this.metricsProperties.getWeb().getServer().getRequest().getMetricName();
String name = (observationName != null) ? observationName : metricName;
String name = httpRequestsMetricName(this.observationProperties, this.metricsProperties);
ServerRequestObservationConvention convention = new DefaultServerRequestObservationConvention(name);
WebMvcTagsProvider tagsProvider = customTagsProvider.getIfAvailable();
List<WebMvcTagsContributor> contributors = contributorsProvider.orderedStream().toList();
@ -101,6 +98,13 @@ public class WebMvcObservationAutoConfiguration {
return registration;
}
private static String httpRequestsMetricName(ObservationProperties observationProperties,
MetricsProperties metricsProperties) {
String observationName = observationProperties.getHttp().getServer().getRequests().getName();
return (observationName != null) ? observationName
: metricsProperties.getWeb().getServer().getRequest().getMetricName();
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(MeterRegistry.class)
@ConditionalOnBean(MeterRegistry.class)
@ -108,11 +112,12 @@ public class WebMvcObservationAutoConfiguration {
@Bean
@Order(0)
MeterFilter metricsHttpServerUriTagFilter(MetricsProperties properties) {
String metricName = properties.getWeb().getServer().getRequest().getMetricName();
MeterFilter metricsHttpServerUriTagFilter(MetricsProperties metricsProperties,
ObservationProperties observationProperties) {
String name = httpRequestsMetricName(observationProperties, metricsProperties);
MeterFilter filter = new OnlyOnceLoggingDenyMeterFilter(
() -> String.format("Reached the maximum number of URI tags for '%s'.", metricName));
return MeterFilter.maximumAllowableTags(metricName, "uri", properties.getWeb().getServer().getMaxUriTags(),
() -> String.format("Reached the maximum number of URI tags for '%s'.", name));
return MeterFilter.maximumAllowableTags(name, "uri", metricsProperties.getWeb().getServer().getMaxUriTags(),
filter);
}

@ -16,21 +16,28 @@
package org.springframework.boot.actuate.autoconfigure.observation.web.reactive;
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 org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun;
import org.springframework.boot.actuate.autoconfigure.metrics.web.TestController;
import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration;
import org.springframework.boot.actuate.metrics.web.reactive.server.DefaultWebFluxTagsProvider;
import org.springframework.boot.actuate.metrics.web.reactive.server.WebFluxTagsContributor;
import org.springframework.boot.actuate.metrics.web.reactive.server.WebFluxTagsProvider;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
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.test.web.reactive.server.WebTestClient;
import org.springframework.web.filter.reactive.ServerHttpObservationFilter;
import org.springframework.web.server.ServerWebExchange;
@ -76,6 +83,75 @@ class WebFluxObservationAutoConfigurationTests {
});
}
@Test
void afterMaxUrisReachedFurtherUrisAreDenied(CapturedOutput output) {
this.contextRunner.withUserConfiguration(TestController.class)
.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class,
ObservationAutoConfiguration.class, WebFluxAutoConfiguration.class))
.withPropertyValues("management.metrics.web.server.max-uri-tags=2").run((context) -> {
MeterRegistry registry = getInitializedMeterRegistry(context);
assertThat(registry.get("http.server.requests").meters().size()).isLessThanOrEqualTo(2);
assertThat(output).contains("Reached the maximum number of URI tags for 'http.server.requests'");
});
}
@Test
@Deprecated(since = "3.0.0", forRemoval = true)
void afterMaxUrisReachedFurtherUrisAreDeniedWhenUsingCustomMetricName(CapturedOutput output) {
this.contextRunner.withUserConfiguration(TestController.class)
.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class,
ObservationAutoConfiguration.class, WebFluxAutoConfiguration.class))
.withPropertyValues("management.metrics.web.server.max-uri-tags=2",
"management.metrics.web.server.request.metric-name=my.http.server.requests")
.run((context) -> {
MeterRegistry registry = getInitializedMeterRegistry(context);
assertThat(registry.get("my.http.server.requests").meters().size()).isLessThanOrEqualTo(2);
assertThat(output).contains("Reached the maximum number of URI tags for 'my.http.server.requests'");
});
}
@Test
void afterMaxUrisReachedFurtherUrisAreDeniedWhenUsingCustomObservationName(CapturedOutput output) {
this.contextRunner.withUserConfiguration(TestController.class)
.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class,
ObservationAutoConfiguration.class, WebFluxAutoConfiguration.class))
.withPropertyValues("management.metrics.web.server.max-uri-tags=2",
"management.observations.http.server.requests.name=my.http.server.requests")
.run((context) -> {
MeterRegistry registry = getInitializedMeterRegistry(context);
assertThat(registry.get("my.http.server.requests").meters().size()).isLessThanOrEqualTo(2);
assertThat(output).contains("Reached the maximum number of URI tags for 'my.http.server.requests'");
});
}
@Test
void shouldNotDenyNorLogIfMaxUrisIsNotReached(CapturedOutput output) {
this.contextRunner.withUserConfiguration(TestController.class)
.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class,
ObservationAutoConfiguration.class, WebFluxAutoConfiguration.class))
.withPropertyValues("management.metrics.web.server.max-uri-tags=5").run((context) -> {
MeterRegistry registry = getInitializedMeterRegistry(context);
assertThat(registry.get("http.server.requests").meters()).hasSize(3);
assertThat(output)
.doesNotContain("Reached the maximum number of URI tags for 'http.server.requests'");
});
}
private MeterRegistry getInitializedMeterRegistry(AssertableReactiveWebApplicationContext context)
throws Exception {
return getInitializedMeterRegistry(context, "/test0", "/test1", "/test2");
}
private MeterRegistry getInitializedMeterRegistry(AssertableReactiveWebApplicationContext context, String... urls)
throws Exception {
assertThat(context).hasSingleBean(ServerHttpObservationFilter.class);
WebTestClient client = WebTestClient.bindToApplicationContext(context).build();
for (String url : urls) {
client.get().uri(url).exchange().expectStatus().isOk();
}
return context.getBean(MeterRegistry.class);
}
@Deprecated(since = "3.0.0", forRemoval = true)
@Configuration(proxyBeanMethods = false)
static class CustomTagsProviderConfiguration {

@ -148,6 +148,35 @@ class WebMvcObservationAutoConfigurationTests {
});
}
@Test
@Deprecated(since = "3.0.0", forRemoval = true)
void afterMaxUrisReachedFurtherUrisAreDeniedWhenUsingCustomMetricName(CapturedOutput output) {
this.contextRunner.withUserConfiguration(TestController.class)
.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class,
ObservationAutoConfiguration.class, WebMvcAutoConfiguration.class))
.withPropertyValues("management.metrics.web.server.max-uri-tags=2",
"management.metrics.web.server.request.metric-name=my.http.server.requests")
.run((context) -> {
MeterRegistry registry = getInitializedMeterRegistry(context);
assertThat(registry.get("my.http.server.requests").meters().size()).isLessThanOrEqualTo(2);
assertThat(output).contains("Reached the maximum number of URI tags for 'my.http.server.requests'");
});
}
@Test
void afterMaxUrisReachedFurtherUrisAreDeniedWhenUsingCustomObservationName(CapturedOutput output) {
this.contextRunner.withUserConfiguration(TestController.class)
.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class,
ObservationAutoConfiguration.class, WebMvcAutoConfiguration.class))
.withPropertyValues("management.metrics.web.server.max-uri-tags=2",
"management.observations.http.server.requests.name=my.http.server.requests")
.run((context) -> {
MeterRegistry registry = getInitializedMeterRegistry(context);
assertThat(registry.get("my.http.server.requests").meters().size()).isLessThanOrEqualTo(2);
assertThat(output).contains("Reached the maximum number of URI tags for 'my.http.server.requests'");
});
}
@Test
void shouldNotDenyNorLogIfMaxUrisIsNotReached(CapturedOutput output) {
this.contextRunner.withUserConfiguration(TestController.class)

Loading…
Cancel
Save