diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/jms/JmsTemplateObservationAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/jms/JmsTemplateObservationAutoConfiguration.java deleted file mode 100644 index 9629468e605..00000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/jms/JmsTemplateObservationAutoConfiguration.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012-2023 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.observation.jms; - -import io.micrometer.jakarta9.instrument.jms.JmsPublishObservationContext; -import io.micrometer.observation.Observation; -import io.micrometer.observation.ObservationRegistry; -import jakarta.jms.Message; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfiguration; -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.jms.JmsAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.jms.core.JmsTemplate; - -/** - * {@link EnableAutoConfiguration Auto-configuration} for instrumenting - * {@link JmsTemplate} beans for Observability. - * - * @author Brian Clozel - * @since 3.2.0 - */ -@AutoConfiguration(after = { JmsAutoConfiguration.class, ObservationAutoConfiguration.class }) -@ConditionalOnBean({ ObservationRegistry.class, JmsTemplate.class }) -@ConditionalOnClass({ Observation.class, Message.class, JmsTemplate.class, JmsPublishObservationContext.class }) -public class JmsTemplateObservationAutoConfiguration { - - @Bean - static JmsTemplateObservationPostProcessor jmsTemplateObservationPostProcessor( - ObjectProvider observationRegistry) { - return new JmsTemplateObservationPostProcessor(observationRegistry); - } - - static class JmsTemplateObservationPostProcessor implements BeanPostProcessor { - - private final ObjectProvider observationRegistry; - - JmsTemplateObservationPostProcessor(ObjectProvider observationRegistry) { - this.observationRegistry = observationRegistry; - } - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof JmsTemplate jmsTemplate) { - this.observationRegistry.ifAvailable(jmsTemplate::setObservationRegistry); - } - return bean; - } - - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/jms/package-info.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/jms/package-info.java deleted file mode 100644 index 417a73aed67..00000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/jms/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2012-2023 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 JMS observations. - */ -package org.springframework.boot.actuate.autoconfigure.observation.jms; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index b1e23fd863f..f48e8e19f43 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -71,7 +71,6 @@ org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdMetri org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontMetricsExportAutoConfiguration org.springframework.boot.actuate.autoconfigure.observation.batch.BatchObservationAutoConfiguration org.springframework.boot.actuate.autoconfigure.observation.graphql.GraphQlObservationAutoConfiguration -org.springframework.boot.actuate.autoconfigure.observation.jms.JmsTemplateObservationAutoConfiguration org.springframework.boot.actuate.autoconfigure.metrics.integration.IntegrationMetricsAutoConfiguration org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration org.springframework.boot.actuate.autoconfigure.metrics.jersey.JerseyServerMetricsAutoConfiguration diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/observation/jms/JmsTemplateObservationAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/observation/jms/JmsTemplateObservationAutoConfigurationTests.java deleted file mode 100644 index dd097676b2d..00000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/observation/jms/JmsTemplateObservationAutoConfigurationTests.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2012-2023 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.observation.jms; - -import jakarta.jms.ConnectionFactory; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration; -import org.springframework.boot.test.context.FilteredClassLoader; -import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.context.annotation.Bean; -import org.springframework.jms.core.JmsTemplate; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link JmsTemplateObservationAutoConfiguration}. - * - * @author Brian Clozel - */ -class JmsTemplateObservationAutoConfigurationTests { - - ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(JmsAutoConfiguration.class, ObservationAutoConfiguration.class, - JmsTemplateObservationAutoConfiguration.class)) - .withUserConfiguration(JmsConnectionConfiguration.class); - - @Test - void shouldConfigureObservationRegistryOnTemplate() { - this.contextRunner.run((context) -> { - JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); - assertThat(jmsTemplate).extracting("observationRegistry").isNotNull(); - }); - } - - @Test - void shouldBackOffWhenMicrometerJakartaIsNotPresent() { - this.contextRunner.withClassLoader(new FilteredClassLoader("io.micrometer.jakarta")).run((context) -> { - JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); - assertThat(jmsTemplate).extracting("observationRegistry").isNull(); - }); - } - - static class JmsConnectionConfiguration { - - @Bean - ConnectionFactory connectionFactory() { - return mock(ConnectionFactory.class); - } - - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/DefaultJmsListenerContainerFactoryConfigurer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/DefaultJmsListenerContainerFactoryConfigurer.java index 2e5f1cc58a0..26e511dbb9f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/DefaultJmsListenerContainerFactoryConfigurer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/DefaultJmsListenerContainerFactoryConfigurer.java @@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.jms; import java.time.Duration; +import io.micrometer.observation.ObservationRegistry; import jakarta.jms.ConnectionFactory; import jakarta.jms.ExceptionListener; @@ -49,6 +50,8 @@ public final class DefaultJmsListenerContainerFactoryConfigurer { private JmsProperties jmsProperties; + private ObservationRegistry observationRegistry; + /** * Set the {@link DestinationResolver} to use or {@code null} if no destination * resolver should be associated with the factory by default. @@ -93,6 +96,15 @@ public final class DefaultJmsListenerContainerFactoryConfigurer { this.jmsProperties = jmsProperties; } + /** + * Set the {@link ObservationRegistry} to use. + * @param observationRegistry the {@link ObservationRegistry} + * @since 3.2.1 + */ + public void setObservationRegistry(ObservationRegistry observationRegistry) { + this.observationRegistry = observationRegistry; + } + /** * Configure the specified jms listener container factory. The factory can be further * tuned and default settings can be overridden. @@ -115,6 +127,7 @@ public final class DefaultJmsListenerContainerFactoryConfigurer { if (this.transactionManager == null && sessionProperties.getTransacted() == null) { factory.setSessionTransacted(true); } + map.from(this.observationRegistry).to(factory::setObservationRegistry); map.from(sessionProperties::getTransacted).to(factory::setSessionTransacted); map.from(listenerProperties::isAutoStartup).to(factory::setAutoStartup); map.from(listenerProperties::formatConcurrency).to(factory::setConcurrency); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAnnotationDrivenConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAnnotationDrivenConfiguration.java index c503fa51842..50886368340 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAnnotationDrivenConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAnnotationDrivenConfiguration.java @@ -16,6 +16,7 @@ package org.springframework.boot.autoconfigure.jms; +import io.micrometer.observation.ObservationRegistry; import jakarta.jms.ConnectionFactory; import jakarta.jms.ExceptionListener; @@ -53,15 +54,19 @@ class JmsAnnotationDrivenConfiguration { private final ObjectProvider exceptionListener; + private final ObjectProvider observationRegistry; + private final JmsProperties properties; JmsAnnotationDrivenConfiguration(ObjectProvider destinationResolver, ObjectProvider transactionManager, ObjectProvider messageConverter, - ObjectProvider exceptionListener, JmsProperties properties) { + ObjectProvider exceptionListener, + ObjectProvider observationRegistry, JmsProperties properties) { this.destinationResolver = destinationResolver; this.transactionManager = transactionManager; this.messageConverter = messageConverter; this.exceptionListener = exceptionListener; + this.observationRegistry = observationRegistry; this.properties = properties; } @@ -73,6 +78,7 @@ class JmsAnnotationDrivenConfiguration { configurer.setTransactionManager(this.transactionManager.getIfUnique()); configurer.setMessageConverter(this.messageConverter.getIfUnique()); configurer.setExceptionListener(this.exceptionListener.getIfUnique()); + configurer.setObservationRegistry(this.observationRegistry.getIfUnique()); configurer.setJmsProperties(this.properties); return configurer; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java index 2c2ba4b5a0b..44b049a657e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java @@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.jms; import java.time.Duration; import java.util.List; +import io.micrometer.observation.ObservationRegistry; import jakarta.jms.ConnectionFactory; import jakarta.jms.Message; @@ -74,12 +75,16 @@ public class JmsAutoConfiguration { private final ObjectProvider messageConverter; + private final ObjectProvider observationRegistry; + public JmsTemplateConfiguration(JmsProperties properties, ObjectProvider destinationResolver, - ObjectProvider messageConverter) { + ObjectProvider messageConverter, + ObjectProvider observationRegistry) { this.properties = properties; this.destinationResolver = destinationResolver; this.messageConverter = messageConverter; + this.observationRegistry = observationRegistry; } @Bean @@ -91,6 +96,7 @@ public class JmsAutoConfiguration { template.setPubSubDomain(this.properties.isPubSubDomain()); map.from(this.destinationResolver::getIfUnique).whenNonNull().to(template::setDestinationResolver); map.from(this.messageConverter::getIfUnique).whenNonNull().to(template::setMessageConverter); + map.from(this.observationRegistry::getIfUnique).whenNonNull().to(template::setObservationRegistry); mapTemplateProperties(this.properties.getTemplate(), template); return template; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java index b9b6025bae4..7ea7a0446e1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java @@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.jms; import java.io.IOException; +import io.micrometer.observation.ObservationRegistry; import jakarta.jms.ConnectionFactory; import jakarta.jms.ExceptionListener; import jakarta.jms.Session; @@ -258,6 +259,17 @@ class JmsAutoConfigurationTests { }); } + @Test + void testDefaultContainerFactoryWithObservationRegistry() { + ObservationRegistry observationRegistry = mock(ObservationRegistry.class); + this.contextRunner.withUserConfiguration(EnableJmsConfiguration.class) + .withBean(ObservationRegistry.class, () -> observationRegistry) + .run((context) -> { + DefaultMessageListenerContainer container = getContainer(context, "jmsListenerContainerFactory"); + assertThat(container.getObservationRegistry()).isSameAs(observationRegistry); + }); + } + @Test void testCustomContainerFactoryWithConfigurer() { this.contextRunner.withUserConfiguration(TestConfiguration9.class, EnableJmsConfiguration.class) @@ -290,6 +302,17 @@ class JmsAutoConfigurationTests { .isSameAs(context.getBean("myDestinationResolver"))); } + @Test + void testJmsTemplateWithObservationRegistry() { + ObservationRegistry observationRegistry = mock(ObservationRegistry.class); + this.contextRunner.withUserConfiguration(EnableJmsConfiguration.class) + .withBean(ObservationRegistry.class, () -> observationRegistry) + .run((context) -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + assertThat(jmsTemplate).extracting("observationRegistry").isSameAs(observationRegistry); + }); + } + @Test void testJmsTemplateFullCustomization() { this.contextRunner.withUserConfiguration(MessageConvertersConfiguration.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 ba8ebca1706..7c654a9438d 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 @@ -745,10 +745,9 @@ Metrics are tagged by the name of the executor, which is derived from the bean n [[actuator.metrics.supported.jms]] ==== JMS Metrics -Auto-configuration enables the instrumentation of all available `JmsTemplate` beans. -`JmsMessagingTemplate` instances built with instrumented `JmsTemplate` beans will also record observations. -See the {spring-framework-docs}/integration/observability.html#observability.jms.publish[Spring Framework reference documentation for more information on produced observations]. - +Auto-configuration enables the instrumentation of all available `JmsTemplate` beans and `@JmsListener` annotated methods. +This will produce `"jms.message.publish"` and `"jms.message.process"` metrics respectively. +See the {spring-framework-docs}/integration/observability.html#observability.jms[Spring Framework reference documentation for more information on produced observations]. [[actuator.metrics.supported.spring-mvc]] diff --git a/src/checkstyle/import-control.xml b/src/checkstyle/import-control.xml index 78d5bbabeab..b3c993a4543 100644 --- a/src/checkstyle/import-control.xml +++ b/src/checkstyle/import-control.xml @@ -1,6 +1,7 @@ +