diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle index 1af4d8d6b9..62389be575 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle @@ -107,12 +107,6 @@ dependencies { exclude group: "javax.xml.bind", module: "jaxb-api" exclude group: "org.jboss.spec.javax.transaction", module: "jboss-transaction-api_1.2_spec" } - optional("org.hibernate:hibernate-micrometer") { - exclude group: "javax.activation", module: "javax.activation-api" - exclude group: "javax.persistence", module: "javax.persistence-api" - exclude group: "javax.xml.bind", module: "jaxb-api" - exclude group: "org.jboss.spec.javax.transaction", module: "jboss-transaction-api_1.2_spec" - } optional("org.hibernate.validator:hibernate-validator") optional("org.influxdb:influxdb-java") optional("org.jolokia:jolokia-core") diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/orm/jpa/HibernateMetricsAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/orm/jpa/HibernateMetricsAutoConfiguration.java deleted file mode 100644 index baf55db1fb..0000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/orm/jpa/HibernateMetricsAutoConfiguration.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2012-2021 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 - * - * https://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.orm.jpa; - -import java.util.Collections; -import java.util.Map; - -import javax.persistence.EntityManagerFactory; -import javax.persistence.PersistenceException; - -import io.micrometer.core.instrument.MeterRegistry; -import org.hibernate.SessionFactory; -import org.hibernate.stat.HibernateMetrics; - -import org.springframework.beans.factory.SmartInitializingSingleton; -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.orm.jpa.HibernateJpaAutoConfiguration; -import org.springframework.context.annotation.Configuration; -import org.springframework.util.StringUtils; - -/** - * {@link EnableAutoConfiguration Auto-configuration} for metrics on all available - * Hibernate {@link EntityManagerFactory} instances that have statistics enabled. - * - * @author Rui Figueira - * @author Stephane Nicoll - * @since 2.1.0 - */ -@Configuration(proxyBeanMethods = false) -@AutoConfigureAfter({ MetricsAutoConfiguration.class, HibernateJpaAutoConfiguration.class, - SimpleMetricsExportAutoConfiguration.class }) -@ConditionalOnClass({ EntityManagerFactory.class, SessionFactory.class, HibernateMetrics.class, MeterRegistry.class }) -@ConditionalOnBean({ EntityManagerFactory.class, MeterRegistry.class }) -public class HibernateMetricsAutoConfiguration implements SmartInitializingSingleton { - - private static final String ENTITY_MANAGER_FACTORY_SUFFIX = "entityManagerFactory"; - - private final Map entityManagerFactories; - - private final MeterRegistry meterRegistry; - - public HibernateMetricsAutoConfiguration(Map entityManagerFactories, - MeterRegistry meterRegistry) { - this.entityManagerFactories = entityManagerFactories; - this.meterRegistry = meterRegistry; - } - - @Override - public void afterSingletonsInstantiated() { - bindEntityManagerFactoriesToRegistry(this.entityManagerFactories, this.meterRegistry); - } - - public void bindEntityManagerFactoriesToRegistry(Map entityManagerFactories, - MeterRegistry registry) { - entityManagerFactories.forEach((name, factory) -> bindEntityManagerFactoryToRegistry(name, factory, registry)); - } - - private void bindEntityManagerFactoryToRegistry(String beanName, EntityManagerFactory entityManagerFactory, - MeterRegistry registry) { - String entityManagerFactoryName = getEntityManagerFactoryName(beanName); - try { - new HibernateMetrics(entityManagerFactory.unwrap(SessionFactory.class), entityManagerFactoryName, - Collections.emptyList()).bindTo(registry); - } - catch (PersistenceException ex) { - // Continue - } - } - - /** - * Get the name of an {@link EntityManagerFactory} based on its {@code beanName}. - * @param beanName the name of the {@link EntityManagerFactory} bean - * @return a name for the given entity manager factory - */ - private String getEntityManagerFactoryName(String beanName) { - if (beanName.length() > ENTITY_MANAGER_FACTORY_SUFFIX.length() - && StringUtils.endsWithIgnoreCase(beanName, ENTITY_MANAGER_FACTORY_SUFFIX)) { - return beanName.substring(0, beanName.length() - ENTITY_MANAGER_FACTORY_SUFFIX.length()); - } - return beanName; - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/orm/jpa/package-info.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/orm/jpa/package-info.java deleted file mode 100644 index e4bd33fc61..0000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/orm/jpa/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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 JPA metrics. - */ -package org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa; 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 3c25ddb134..7b26c7f4e2 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 @@ -71,7 +71,6 @@ org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.Wavefron org.springframework.boot.actuate.autoconfigure.metrics.integration.IntegrationMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.mongo.MongoMetricsAutoConfiguration,\ -org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.r2dbc.ConnectionPoolMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.redis.LettuceMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.startup.StartupTimeMetricsListenerAutoConfiguration,\ diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/orm/jpa/HibernateMetricsAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/orm/jpa/HibernateMetricsAutoConfigurationTests.java deleted file mode 100644 index 2f372877b9..0000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/orm/jpa/HibernateMetricsAutoConfigurationTests.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2012-2021 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 - * - * https://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.orm.jpa; - -import java.util.HashMap; -import java.util.Map; - -import javax.persistence.Entity; -import javax.persistence.EntityManagerFactory; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.PersistenceException; -import javax.sql.DataSource; - -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.simple.SimpleMeterRegistry; -import org.hibernate.SessionFactory; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentMatchers; - -import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryBuilderCustomizer; -import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; -import org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration; -import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; -import org.springframework.boot.test.context.FilteredClassLoader; -import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.core.task.SimpleAsyncTaskExecutor; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; -import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link HibernateMetricsAutoConfiguration}. - * - * @author Rui Figueira - * @author Stephane Nicoll - */ -class HibernateMetricsAutoConfigurationTests { - - private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().with(MetricsRun.simple()) - .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class, - HibernateJpaAutoConfiguration.class, HibernateMetricsAutoConfiguration.class)) - .withUserConfiguration(BaseConfiguration.class); - - @Test - void autoConfiguredEntityManagerFactoryWithStatsIsInstrumented() { - this.contextRunner.withPropertyValues("spring.jpa.properties.hibernate.generate_statistics:true") - .run((context) -> { - MeterRegistry registry = context.getBean(MeterRegistry.class); - registry.get("hibernate.statements").tags("entityManagerFactory", "entityManagerFactory").meter(); - }); - } - - @Test - void autoConfiguredEntityManagerFactoryWithoutStatsIsNotInstrumented() { - this.contextRunner.withPropertyValues("spring.jpa.properties.hibernate.generate_statistics:false") - .run((context) -> { - context.getBean(EntityManagerFactory.class).unwrap(SessionFactory.class); - MeterRegistry registry = context.getBean(MeterRegistry.class); - assertThat(registry.find("hibernate.statements").meter()).isNull(); - }); - } - - @Test - void entityManagerFactoryInstrumentationCanBeDisabled() { - this.contextRunner.withPropertyValues("management.metrics.enable.hibernate=false", - "spring.jpa.properties.hibernate.generate_statistics:true").run((context) -> { - context.getBean(EntityManagerFactory.class).unwrap(SessionFactory.class); - MeterRegistry registry = context.getBean(MeterRegistry.class); - assertThat(registry.find("hibernate.statements").meter()).isNull(); - }); - } - - @Test - void allEntityManagerFactoriesCanBeInstrumented() { - this.contextRunner.withPropertyValues("spring.jpa.properties.hibernate.generate_statistics:true") - .withUserConfiguration(TwoEntityManagerFactoriesConfiguration.class).run((context) -> { - context.getBean("firstEntityManagerFactory", EntityManagerFactory.class) - .unwrap(SessionFactory.class); - context.getBean("secondOne", EntityManagerFactory.class).unwrap(SessionFactory.class); - MeterRegistry registry = context.getBean(MeterRegistry.class); - registry.get("hibernate.statements").tags("entityManagerFactory", "first").meter(); - registry.get("hibernate.statements").tags("entityManagerFactory", "secondOne").meter(); - }); - } - - @Test - void entityManagerFactoryInstrumentationIsDisabledIfNotHibernateSessionFactory() { - this.contextRunner.withPropertyValues("spring.jpa.properties.hibernate.generate_statistics:true") - .withUserConfiguration(NonHibernateEntityManagerFactoryConfiguration.class).run((context) -> { - // ensure EntityManagerFactory is not a Hibernate SessionFactory - assertThatThrownBy(() -> context.getBean(EntityManagerFactory.class).unwrap(SessionFactory.class)) - .isInstanceOf(PersistenceException.class); - MeterRegistry registry = context.getBean(MeterRegistry.class); - assertThat(registry.find("hibernate.statements").meter()).isNull(); - }); - } - - @Test - void entityManagerFactoryInstrumentationIsDisabledIfHibernateIsNotAvailable() { - this.contextRunner.withClassLoader(new FilteredClassLoader(SessionFactory.class)) - .withUserConfiguration(NonHibernateEntityManagerFactoryConfiguration.class).run((context) -> { - assertThat(context).doesNotHaveBean(HibernateMetricsAutoConfiguration.class); - MeterRegistry registry = context.getBean(MeterRegistry.class); - assertThat(registry.find("hibernate.statements").meter()).isNull(); - }); - } - - @Test - void entityManagerFactoryInstrumentationDoesNotDeadlockWithDeferredInitialization() { - this.contextRunner.withPropertyValues("spring.jpa.properties.hibernate.generate_statistics:true", - "spring.sql.init.schema-locations:city-schema.sql", "spring.sql.init.data-locations=city-data.sql") - .withConfiguration(AutoConfigurations.of(SqlInitializationAutoConfiguration.class)) - .withBean(EntityManagerFactoryBuilderCustomizer.class, - () -> (builder) -> builder.setBootstrapExecutor(new SimpleAsyncTaskExecutor())) - .run((context) -> { - JdbcTemplate jdbcTemplate = new JdbcTemplate(context.getBean(DataSource.class)); - assertThat(jdbcTemplate.queryForObject("SELECT COUNT(*) from CITY", Integer.class)).isEqualTo(1); - MeterRegistry registry = context.getBean(MeterRegistry.class); - registry.get("hibernate.statements").tags("entityManagerFactory", "entityManagerFactory").meter(); - }); - } - - @Configuration(proxyBeanMethods = false) - static class BaseConfiguration { - - @Bean - SimpleMeterRegistry simpleMeterRegistry() { - return new SimpleMeterRegistry(); - } - - } - - @Entity - static class MyEntity { - - @Id - @GeneratedValue - private Long id; - - } - - @Configuration(proxyBeanMethods = false) - static class TwoEntityManagerFactoriesConfiguration { - - private static final Class[] PACKAGE_CLASSES = new Class[] { MyEntity.class }; - - @Primary - @Bean - LocalContainerEntityManagerFactoryBean firstEntityManagerFactory(DataSource ds) { - return createSessionFactory(ds); - } - - @Bean - LocalContainerEntityManagerFactoryBean secondOne(DataSource ds) { - return createSessionFactory(ds); - } - - private LocalContainerEntityManagerFactoryBean createSessionFactory(DataSource ds) { - Map jpaProperties = new HashMap<>(); - jpaProperties.put("hibernate.generate_statistics", "true"); - return new EntityManagerFactoryBuilder(new HibernateJpaVendorAdapter(), jpaProperties, null).dataSource(ds) - .packages(PACKAGE_CLASSES).build(); - } - - } - - @Configuration(proxyBeanMethods = false) - static class NonHibernateEntityManagerFactoryConfiguration { - - @Bean - EntityManagerFactory entityManagerFactory() { - EntityManagerFactory mockedFactory = mock(EntityManagerFactory.class); - // enforces JPA contract - given(mockedFactory.unwrap(ArgumentMatchers.>any())) - .willThrow(PersistenceException.class); - return mockedFactory; - } - - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/test/MetricsIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/test/MetricsIntegrationTests.java index 842c7a0f99..8c2552af31 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/test/MetricsIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/test/MetricsIntegrationTests.java @@ -41,7 +41,6 @@ import org.springframework.boot.actuate.autoconfigure.metrics.SystemMetricsAutoC import org.springframework.boot.actuate.autoconfigure.metrics.amqp.RabbitMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.web.client.HttpClientMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.web.reactive.WebFluxMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration; @@ -139,9 +138,8 @@ class MetricsIntegrationTests { @ImportAutoConfiguration({ MetricsAutoConfiguration.class, JvmMetricsAutoConfiguration.class, LogbackMetricsAutoConfiguration.class, SystemMetricsAutoConfiguration.class, RabbitMetricsAutoConfiguration.class, CacheMetricsAutoConfiguration.class, - DataSourcePoolMetricsAutoConfiguration.class, HibernateMetricsAutoConfiguration.class, - HttpClientMetricsAutoConfiguration.class, WebFluxMetricsAutoConfiguration.class, - WebMvcMetricsAutoConfiguration.class, JacksonAutoConfiguration.class, + DataSourcePoolMetricsAutoConfiguration.class, HttpClientMetricsAutoConfiguration.class, + WebFluxMetricsAutoConfiguration.class, WebMvcMetricsAutoConfiguration.class, JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, RestTemplateAutoConfiguration.class, WebMvcAutoConfiguration.class, DispatcherServletAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class }) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc index 82628b5ec7..088872553c 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc @@ -853,25 +853,6 @@ Each metric is tagged by the name of the pool (you can control it with `spring.d -[[actuator.metrics.supported.hibernate]] -==== Hibernate Metrics -If `org.hibernate:hibernate-micrometer` is on the classpath, all available Hibernate `EntityManagerFactory` instances that have statistics enabled are instrumented with a metric named `hibernate`. - -Metrics are also tagged by the name of the `EntityManagerFactory`, which is derived from the bean name. - -To enable statistics, the standard JPA property `hibernate.generate_statistics` must be set to `true`. -You can enable that on the auto-configured `EntityManagerFactory`: - -[source,yaml,indent=0,subs="verbatim",configprops,configblocks] ----- - spring: - jpa: - properties: - "[hibernate.generate_statistics]": true ----- - - - [[actuator.metrics.supported.spring-data-repository]] ==== Spring Data Repository Metrics Auto-configuration enables the instrumentation of all Spring Data `Repository` method invocations.