diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml b/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml
index f8c2c72029ab..ac15bb60310d 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/web/jersey/JerseyServerMetricsAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/web/jersey/JerseyServerMetricsAutoConfiguration.java
new file mode 100644
index 000000000000..59ffcc93cfc2
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/web/jersey/JerseyServerMetricsAutoConfiguration.java
@@ -0,0 +1,82 @@
+/*
+ * 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.web.jersey;
+
+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.MetricsProperties;
+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 instrumentation of Jersey servlet-based request mappings.
+ *
+ * @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})
+@ConditionalOnMissingBean(type = "org.springframework.web.servlet.DispatcherServlet")
+@EnableConfigurationProperties(MetricsProperties.class)
+public class JerseyServerMetricsAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean(JerseyTagsProvider.class)
+ public DefaultJerseyTagsProvider jerseyTagsProvider() {
+ return new DefaultJerseyTagsProvider();
+ }
+
+ @Bean
+ public ResourceConfigCustomizer jerseyServerMetricsResourceConfigCustomizer(
+ final MeterRegistry meterRegistry,
+ final MetricsProperties properties,
+ final JerseyTagsProvider tagsProvider) {
+ final MetricsProperties.Web.Server serverProperties = properties.getWeb().getServer();
+ return (config) -> config.register(new MetricsApplicationEventListener(meterRegistry, tagsProvider,
+ serverProperties.getRequestsMetricName(), serverProperties.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/web/jersey/package-info.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/web/jersey/package-info.java
new file mode 100644
index 000000000000..77ff7c6ff263
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/web/jersey/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 / JAX-RS actuator metrics.
+ */
+package org.springframework.boot.actuate.autoconfigure.metrics.web.jersey;
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 01ba105602e7..c2d75289b62d 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
@@ -51,6 +51,7 @@ org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.Wavefron
org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.web.client.RestTemplateMetricsAutoConfiguration,\
+org.springframework.boot.actuate.autoconfigure.metrics.web.jersey.JerseyServerMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.web.reactive.WebFluxMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.web.tomcat.TomcatMetricsAutoConfiguration,\
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/web/jersey/JerseyServerMetricsAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/web/jersey/JerseyServerMetricsAutoConfigurationTests.java
new file mode 100644
index 000000000000..6dfbc090c6f0
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/web/jersey/JerseyServerMetricsAutoConfigurationTests.java
@@ -0,0 +1,112 @@
+/*
+ * 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.web.jersey;
+
+import io.micrometer.core.instrument.Tag;
+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.CompositeMeterRegistryAutoConfiguration;
+import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
+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.test.context.FilteredClassLoader;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
+import org.springframework.context.annotation.Bean;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link JerseyServerMetricsAutoConfiguration}.
+ *
+ * @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()
+ .withConfiguration(AutoConfigurations.of(
+ JerseyAutoConfiguration.class, MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class,
+ JerseyServerMetricsAutoConfiguration.class)
+ )
+ .withUserConfiguration(JerseyConfig.class);
+
+ @Test
+ public void shouldOnlyBeActiveInWebApplicationContext() {
+ this.contextRunner.run(ctx -> assertThat(ctx).doesNotHaveBean(ResourceConfigCustomizer.class));
+ }
+
+ @Test
+ public void shouldProvideALlNecessaryBeans() {
+ this.webContextRunner.run(ctx -> assertThat(ctx)
+ .hasSingleBean(DefaultJerseyTagsProvider.class)
+ .hasSingleBean(ResourceConfigCustomizer.class)
+ );
+ }
+
+ @Test
+ public void shouldHonorExistingTagProvider() {
+ this.webContextRunner
+ .withUserConfiguration(JerseyServerMetricConfig.class)
+ .run(ctx -> assertThat(ctx).hasSingleBean(ATagsProvider.class));
+ }
+
+ @Test
+ public void doesNotFailWithoutJersey2Metrics() {
+ this.webContextRunner
+ .withClassLoader(new FilteredClassLoader(MetricsApplicationEventListener.class))
+ .run(ctx -> assertThat(ctx).doesNotHaveBean(ResourceConfigCustomizer.class));
+ }
+
+ static class JerseyConfig {
+ @Bean
+ ResourceConfig resourceConfig() {
+ return new ResourceConfig();
+ }
+ }
+
+ static class JerseyServerMetricConfig {
+ @Bean
+ JerseyTagsProvider jerseyTagsProvider() {
+ return new ATagsProvider();
+ }
+ }
+
+ static class ATagsProvider implements JerseyTagsProvider {
+
+ @Override
+ public Iterable httpRequestTags(RequestEvent requestEvent) {
+ return null;
+ }
+
+ @Override
+ public Iterable httpLongRequestTags(RequestEvent requestEvent) {
+ return null;
+ }
+ }
+}
diff --git a/spring-boot-project/spring-boot-dependencies/pom.xml b/spring-boot-project/spring-boot-dependencies/pom.xml
index df5d29db1e7c..8422b516024d 100644
--- a/spring-boot-project/spring-boot-dependencies/pom.xml
+++ b/spring-boot-project/spring-boot-dependencies/pom.xml
@@ -861,6 +861,11 @@
micrometer-core
${micrometer.version}
+
+ io.micrometer
+ micrometer-jersey2
+ ${micrometer.version}
+
io.micrometer
micrometer-registry-atlas
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 e006f6f37ddf..8067e6f92877 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
@@ -1705,6 +1705,48 @@ To customize the tags, provide a `@Bean` that implements `WebFluxTagsProvider`.
+[[production-ready-metrics-spring-mvc]]
+==== Jersey 2 Metrics
+Auto-configuration enables the instrumentation of requests handled by the Jersey 2 implementation of JAX-RS.
+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]
+----
+ @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.web.server.requests-metric-name` property.
+
+By default, Spring MVC-related 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-rest-template]]
==== RestTemplate Metrics
The instrumentation of any `RestTemplate` created using the auto-configured