From dd126faf5ac3a5be4f04d15d5c3e3938db93cf36 Mon Sep 17 00:00:00 2001 From: Michael Weirauch Date: Wed, 14 Mar 2018 17:23:15 +0100 Subject: [PATCH 1/2] Auto-configure Micrometer's Jersey 2 server instrumentation See gh-12482 Co-authored-by: Michael J. Simons --- .../pom.xml | 5 + .../JerseyServerMetricsAutoConfiguration.java | 81 ++++++++ .../server/JerseyServerMetricsProperties.java | 50 +++++ .../metrics/jersey2/server/package-info.java | 20 ++ .../main/resources/META-INF/spring.factories | 1 + ...eyServerMetricsAutoConfigurationTests.java | 174 ++++++++++++++++++ .../asciidoc/production-ready-features.adoc | 41 +++++ 7 files changed, 372 insertions(+) create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfiguration.java create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsProperties.java create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/package-info.java create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfigurationTests.java diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml b/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml index a679534533..15bbe47126 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml @@ -92,6 +92,11 @@ micrometer-core true + + io.micrometer + micrometer-jersey2 + true + io.micrometer micrometer-registry-atlas diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfiguration.java new file mode 100644 index 0000000000..431ec310d2 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfiguration.java @@ -0,0 +1,81 @@ +/* + * Copyright 2012-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.autoconfigure.metrics.jersey2.server; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.jersey2.server.AnnotationFinder; +import io.micrometer.jersey2.server.DefaultJerseyTagsProvider; +import io.micrometer.jersey2.server.JerseyTagsProvider; +import io.micrometer.jersey2.server.MetricsApplicationEventListener; +import org.glassfish.jersey.server.ResourceConfig; + +import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.AnnotationUtils; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for Jersey server instrumentation. + * + * @author Michael Weirauch + * @author Michael Simons + * @since 2.1.0 + */ +@Configuration +@AutoConfigureAfter({ MetricsAutoConfiguration.class, + SimpleMetricsExportAutoConfiguration.class }) +@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) +@ConditionalOnClass({ ResourceConfig.class, MetricsApplicationEventListener.class }) +@ConditionalOnBean({ MeterRegistry.class, ResourceConfig.class }) +@EnableConfigurationProperties(JerseyServerMetricsProperties.class) +public class JerseyServerMetricsAutoConfiguration { + + @Bean + @ConditionalOnMissingBean(JerseyTagsProvider.class) + public DefaultJerseyTagsProvider jerseyTagsProvider() { + return new DefaultJerseyTagsProvider(); + } + + @Bean + public ResourceConfigCustomizer jerseyServerMetricsResourceConfigCustomizer( + MeterRegistry meterRegistry, JerseyServerMetricsProperties properties, + JerseyTagsProvider tagsProvider) { + return (config) -> config.register(new MetricsApplicationEventListener( + meterRegistry, tagsProvider, properties.getRequestsMetricName(), + properties.isAutoTimeRequests(), new AnnotationFinder() { + @Override + public A findAnnotation( + AnnotatedElement annotatedElement, Class annotationType) { + return AnnotationUtils.findAnnotation(annotatedElement, + annotationType); + } + })); + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsProperties.java new file mode 100644 index 0000000000..8fddb1e8a4 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsProperties.java @@ -0,0 +1,50 @@ +/* + * Copyright 2012-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.autoconfigure.metrics.jersey2.server; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Configuration for Jersey server instrumentation. + * + * @author Michael Weirauch + * @since 2.1.0 + */ +@ConfigurationProperties(prefix = "management.metrics.jersey2.server") +public class JerseyServerMetricsProperties { + + private String requestsMetricName = "http.server.requests"; + + private boolean autoTimeRequests = true; + + public String getRequestsMetricName() { + return this.requestsMetricName; + } + + public void setRequestsMetricName(String requestsMetricName) { + this.requestsMetricName = requestsMetricName; + } + + public boolean isAutoTimeRequests() { + return this.autoTimeRequests; + } + + public void setAutoTimeRequests(boolean autoTimeRequests) { + this.autoTimeRequests = autoTimeRequests; + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/package-info.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/package-info.java new file mode 100644 index 0000000000..093d228878 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Auto-configuration for Jersey server actuator metrics. + */ +package org.springframework.boot.actuate.autoconfigure.metrics.jersey2.server; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories index 8539667910..122c561674 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories @@ -61,6 +61,7 @@ org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetri org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdMetricsExportAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontMetricsExportAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration,\ +org.springframework.boot.actuate.autoconfigure.metrics.jersey2.server.JerseyServerMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.web.client.HttpClientMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.web.reactive.WebFluxMetricsAutoConfiguration,\ diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfigurationTests.java new file mode 100644 index 0000000000..6d27eae953 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfigurationTests.java @@ -0,0 +1,174 @@ +/* + * Copyright 2012-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.autoconfigure.metrics.jersey2.server; + +import java.net.URI; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Timer; +import io.micrometer.jersey2.server.DefaultJerseyTagsProvider; +import io.micrometer.jersey2.server.JerseyTagsProvider; +import io.micrometer.jersey2.server.MetricsApplicationEventListener; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.server.monitoring.RequestEvent; +import org.junit.Test; + +import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration; +import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer; +import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.test.context.FilteredClassLoader; +import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.boot.test.context.runner.WebApplicationContextRunner; +import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link JerseyServerMetricsAutoConfiguration}. + * + * @author Michael Weirauch + * @author Michael Simons + */ +public class JerseyServerMetricsAutoConfigurationTests { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .with(MetricsRun.simple()).withConfiguration( + AutoConfigurations.of(JerseyServerMetricsAutoConfiguration.class)); + + private final WebApplicationContextRunner webContextRunner = new WebApplicationContextRunner( + AnnotationConfigServletWebServerApplicationContext::new) + .withConfiguration( + AutoConfigurations.of(JerseyAutoConfiguration.class, + JerseyServerMetricsAutoConfiguration.class, + ServletWebServerFactoryAutoConfiguration.class, + SimpleMetricsExportAutoConfiguration.class, + MetricsAutoConfiguration.class)) + .withUserConfiguration(ResourceConfiguration.class) + .withPropertyValues("server.port:0"); + + @Test + public void shouldOnlyBeActiveInWebApplicationContext() { + this.contextRunner.run((context) -> assertThat(context) + .doesNotHaveBean(ResourceConfigCustomizer.class)); + } + + @Test + public void shouldProvideAllNecessaryBeans() { + this.webContextRunner.run((context) -> assertThat(context) + .hasSingleBean(DefaultJerseyTagsProvider.class) + .hasSingleBean(ResourceConfigCustomizer.class)); + } + + @Test + public void shouldHonorExistingTagProvider() { + this.webContextRunner + .withUserConfiguration(CustomJerseyTagsProviderConfiguration.class) + .run((context) -> assertThat(context) + .hasSingleBean(CustomJerseyTagsProvider.class)); + } + + @Test + public void httpRequestsAreTimed() { + this.webContextRunner.run((context) -> { + doRequest(context); + + MeterRegistry registry = context.getBean(MeterRegistry.class); + Timer timer = registry.get("http.server.requests").tag("uri", "/users/{id}") + .timer(); + assertThat(timer.count()).isEqualTo(1); + }); + } + + @Test + public void noHttpRequestsTimedWhenJerseyInstrumentationMissingFromClasspath() { + this.webContextRunner + .withClassLoader( + new FilteredClassLoader(MetricsApplicationEventListener.class)) + .run((context) -> { + doRequest(context); + + MeterRegistry registry = context.getBean(MeterRegistry.class); + assertThat(registry.find("http.server.requests").timer()).isNull(); + }); + } + + private static void doRequest(AssertableWebApplicationContext context) { + int port = context + .getSourceApplicationContext( + AnnotationConfigServletWebServerApplicationContext.class) + .getWebServer().getPort(); + RestTemplate restTemplate = new RestTemplate(); + restTemplate.getForEntity(URI.create("http://localhost:" + port + "/users/3"), + String.class); + } + + static class ResourceConfiguration { + + @Bean + ResourceConfig resourceConfig() { + return new ResourceConfig().register(new TestResource()); + } + + @Path("/users") + public class TestResource { + + @GET + @Path("/{id}") + public String getUser(@PathParam("id") String id) { + return id; + } + + } + + } + + static class CustomJerseyTagsProviderConfiguration { + + @Bean + JerseyTagsProvider customJerseyTagsProvider() { + return new CustomJerseyTagsProvider(); + } + + } + + static class CustomJerseyTagsProvider implements JerseyTagsProvider { + + @Override + public Iterable httpRequestTags(RequestEvent event) { + return null; + } + + @Override + public Iterable httpLongRequestTags(RequestEvent event) { + return null; + } + + } + +} diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc index 98386320af..40d7d78158 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc @@ -1832,6 +1832,47 @@ To customize the tags, provide a `@Bean` that implements `WebFluxTagsProvider`. +[[production-ready-metrics-jersey-server]] +==== Jersey Server Metrics +Auto-configuration enables the instrumentation of requests handled by the Jersey JAX-RS +implementation. When `management.metrics.jersey2.server.auto-time-requests` is `true`, +this instrumentation occurs for all requests. Alternatively, when set to `false`, you +can enable instrumentation by adding `@Timed` to a request-handling method: + +[source,java,indent=0] +---- + @Component + @Path("/api/people") + @Timed <1> + public class Endpoint { + @GET + @Timed(extraTags = { "region", "us-east-1" }) <2> + @Timed(value = "all.people", longTask = true) <3> + public List listPeople() { ... } + } +---- +<1> On a resource class to enable timings on every request handler in the resource. +<2> On a method to enable for an individual endpoint. This is not necessary if you have it on +the class, but can be used to further customize the timer for this particular endpoint. +<3> On a method with `longTask = true` to enable a long task timer for the method. Long task +timers require a separate metric name, and can be stacked with a short task timer. + +By default, metrics are generated with the name, `http.server.requests`. The name can be +customized by setting the `management.metrics.jersey2.server.requests-metric-name` property. + +By default, Jersey server metrics are tagged with the following information: + +* `method`, the request's method (for example, `GET` or `POST`). +* `uri`, the request's URI template prior to variable substitution, if possible (for +example, `/api/person/{id}`). +* `status`, the response's HTTP status code (for example, `200` or `500`). +* `exception`, the simple class name of any exception that was thrown while handling the +request. + +To customize the tags, provide a `@Bean` that implements `JerseyTagsProvider`. + + + [[production-ready-metrics-http-clients]] ==== HTTP Client Metrics Spring Boot Actuator manages the instrumentation of both `RestTemplate` and `WebClient`. From 72e2313fe84eed695e1e525722f0e05796c51cbb Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 5 Oct 2018 16:03:12 +0100 Subject: [PATCH 2/2] Polish "Auto-configure Micrometer's Jersey 2 server instrumentation" Closes gh-12482 --- .../JerseyServerMetricsAutoConfiguration.java | 58 ++++++++++++++----- .../server => jersey}/package-info.java | 4 +- .../server/JerseyServerMetricsProperties.java | 50 ---------------- .../main/resources/META-INF/spring.factories | 2 +- ...eyServerMetricsAutoConfigurationTests.java | 3 +- .../asciidoc/production-ready-features.adoc | 8 +-- 6 files changed, 52 insertions(+), 73 deletions(-) rename spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/{jersey2/server => jersey}/JerseyServerMetricsAutoConfiguration.java (62%) rename spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/{jersey2/server => jersey}/package-info.java (90%) delete mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsProperties.java rename spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/{jersey2/server => jersey}/JerseyServerMetricsAutoConfigurationTests.java (99%) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey/JerseyServerMetricsAutoConfiguration.java similarity index 62% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfiguration.java rename to spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey/JerseyServerMetricsAutoConfiguration.java index 431ec310d2..4a791db7b0 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey/JerseyServerMetricsAutoConfiguration.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package org.springframework.boot.actuate.autoconfigure.metrics.jersey2.server; +package org.springframework.boot.actuate.autoconfigure.metrics.jersey; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.config.MeterFilter; import io.micrometer.jersey2.server.AnnotationFinder; import io.micrometer.jersey2.server.DefaultJerseyTagsProvider; import io.micrometer.jersey2.server.JerseyTagsProvider; @@ -27,6 +28,9 @@ import io.micrometer.jersey2.server.MetricsApplicationEventListener; import org.glassfish.jersey.server.ResourceConfig; 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.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -39,12 +43,14 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.Order; /** * {@link EnableAutoConfiguration Auto-configuration} for Jersey server instrumentation. * * @author Michael Weirauch * @author Michael Simons + * @author Andy Wilkinson * @since 2.1.0 */ @Configuration @@ -53,9 +59,15 @@ import org.springframework.core.annotation.AnnotationUtils; @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnClass({ ResourceConfig.class, MetricsApplicationEventListener.class }) @ConditionalOnBean({ MeterRegistry.class, ResourceConfig.class }) -@EnableConfigurationProperties(JerseyServerMetricsProperties.class) +@EnableConfigurationProperties(MetricsProperties.class) public class JerseyServerMetricsAutoConfiguration { + private final MetricsProperties properties; + + public JerseyServerMetricsAutoConfiguration(MetricsProperties properties) { + this.properties = properties; + } + @Bean @ConditionalOnMissingBean(JerseyTagsProvider.class) public DefaultJerseyTagsProvider jerseyTagsProvider() { @@ -64,18 +76,36 @@ public class JerseyServerMetricsAutoConfiguration { @Bean public ResourceConfigCustomizer jerseyServerMetricsResourceConfigCustomizer( - MeterRegistry meterRegistry, JerseyServerMetricsProperties properties, - JerseyTagsProvider tagsProvider) { - return (config) -> config.register(new MetricsApplicationEventListener( - meterRegistry, tagsProvider, properties.getRequestsMetricName(), - properties.isAutoTimeRequests(), new AnnotationFinder() { - @Override - public A findAnnotation( - AnnotatedElement annotatedElement, Class annotationType) { - return AnnotationUtils.findAnnotation(annotatedElement, - annotationType); - } - })); + MeterRegistry meterRegistry, JerseyTagsProvider tagsProvider) { + Server server = this.properties.getWeb().getServer(); + return (config) -> { + config.register(new MetricsApplicationEventListener(meterRegistry, + tagsProvider, server.getRequestsMetricName(), + server.isAutoTimeRequests(), new AnnotationUtilsAnnotationFinder())); + }; + } + + @Bean + @Order(0) + public MeterFilter jerseyMetricsUriTagFilter() { + String metricName = this.properties.getWeb().getServer().getRequestsMetricName(); + MeterFilter filter = new OnlyOnceLoggingDenyMeterFilter(() -> String + .format("Reached the maximum number of URI tags for '%s'.", metricName)); + return MeterFilter.maximumAllowableTags(metricName, "uri", + this.properties.getWeb().getServer().getMaxUriTags(), filter); + } + + /** + * An {@link AnnotationFinder} that uses {@link AnnotationUtils}. + */ + private static class AnnotationUtilsAnnotationFinder implements AnnotationFinder { + + @Override + public A findAnnotation(AnnotatedElement annotatedElement, + Class annotationType) { + return AnnotationUtils.findAnnotation(annotatedElement, annotationType); + } + } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/package-info.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey/package-info.java similarity index 90% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/package-info.java rename to spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey/package-info.java index 093d228878..6a57de0f6a 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/package-info.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey/package-info.java @@ -15,6 +15,6 @@ */ /** - * Auto-configuration for Jersey server actuator metrics. + * Auto-configuration for Jersey actuator metrics. */ -package org.springframework.boot.actuate.autoconfigure.metrics.jersey2.server; +package org.springframework.boot.actuate.autoconfigure.metrics.jersey; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsProperties.java deleted file mode 100644 index 8fddb1e8a4..0000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsProperties.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2012-2018 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.autoconfigure.metrics.jersey2.server; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * Configuration for Jersey server instrumentation. - * - * @author Michael Weirauch - * @since 2.1.0 - */ -@ConfigurationProperties(prefix = "management.metrics.jersey2.server") -public class JerseyServerMetricsProperties { - - private String requestsMetricName = "http.server.requests"; - - private boolean autoTimeRequests = true; - - public String getRequestsMetricName() { - return this.requestsMetricName; - } - - public void setRequestsMetricName(String requestsMetricName) { - this.requestsMetricName = requestsMetricName; - } - - public boolean isAutoTimeRequests() { - return this.autoTimeRequests; - } - - public void setAutoTimeRequests(boolean autoTimeRequests) { - this.autoTimeRequests = autoTimeRequests; - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories index 122c561674..29af9cef1b 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories @@ -61,7 +61,7 @@ org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetri org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdMetricsExportAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontMetricsExportAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration,\ -org.springframework.boot.actuate.autoconfigure.metrics.jersey2.server.JerseyServerMetricsAutoConfiguration,\ +org.springframework.boot.actuate.autoconfigure.metrics.jersey.JerseyServerMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.web.client.HttpClientMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.web.reactive.WebFluxMetricsAutoConfiguration,\ diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey/JerseyServerMetricsAutoConfigurationTests.java similarity index 99% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfigurationTests.java rename to spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey/JerseyServerMetricsAutoConfigurationTests.java index 6d27eae953..8fdc463200 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey2/server/JerseyServerMetricsAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/jersey/JerseyServerMetricsAutoConfigurationTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.autoconfigure.metrics.jersey2.server; +package org.springframework.boot.actuate.autoconfigure.metrics.jersey; import java.net.URI; @@ -97,7 +97,6 @@ public class JerseyServerMetricsAutoConfigurationTests { public void httpRequestsAreTimed() { this.webContextRunner.run((context) -> { doRequest(context); - MeterRegistry registry = context.getBean(MeterRegistry.class); Timer timer = registry.get("http.server.requests").tag("uri", "/users/{id}") .timer(); diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc index 40d7d78158..b05de13fcc 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc @@ -1835,9 +1835,9 @@ To customize the tags, provide a `@Bean` that implements `WebFluxTagsProvider`. [[production-ready-metrics-jersey-server]] ==== Jersey Server Metrics Auto-configuration enables the instrumentation of requests handled by the Jersey JAX-RS -implementation. When `management.metrics.jersey2.server.auto-time-requests` is `true`, -this instrumentation occurs for all requests. Alternatively, when set to `false`, you -can enable instrumentation by adding `@Timed` to a request-handling method: +implementation. When `management.metrics.web.server.auto-time-requests` is `true`, this +instrumentation occurs for all requests. Alternatively, when set to `false`, you can +enable instrumentation by adding `@Timed` to a request-handling method: [source,java,indent=0] ---- @@ -1858,7 +1858,7 @@ the class, but can be used to further customize the timer for this particular en timers require a separate metric name, and can be stacked with a short task timer. By default, metrics are generated with the name, `http.server.requests`. The name can be -customized by setting the `management.metrics.jersey2.server.requests-metric-name` property. +customized by setting the `management.metrics.web.server.requests-metric-name` property. By default, Jersey server metrics are tagged with the following information: