hashMap = new HashMap<>();
+
+ for (final String segment : segments) {
+ final int indexOfEqualSign = segment.indexOf("=");
+ final String key = segment.substring(0, indexOfEqualSign);
+ final String value = segment.substring(indexOfEqualSign + 1);
+ hashMap.put(key, value);
+ }
+
+ final String endpoint = hashMap.get(ENDPOINT);
+ final String[] segmentsOfEndpoint = endpoint.split("/");
+ final String host = segmentsOfEndpoint[segmentsOfEndpoint.length - 1];
+ hashMap.put(HOST, host);
+
+ return new ServiceBusKey(hashMap.get(HOST), hashMap.get(SAS_KEY_NAME), hashMap.get(SAS_KEY));
+ }
+
+}
diff --git a/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/jms/ServiceBusJMSAutoConfiguration.java b/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/jms/ServiceBusJMSAutoConfiguration.java
new file mode 100644
index 000000000000..964dbbb8ce27
--- /dev/null
+++ b/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/jms/ServiceBusJMSAutoConfiguration.java
@@ -0,0 +1,83 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.microsoft.azure.spring.autoconfigure.jms;
+
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
+import org.springframework.jms.config.JmsListenerContainerFactory;
+import org.springframework.jms.connection.CachingConnectionFactory;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.listener.MessageListenerContainer;
+
+import javax.jms.ConnectionFactory;
+
+/**
+ * Auto-configuration for Service Bus JMS.
+ *
+ * The configuration will not be activated if no {@literal spring.jms.servicebus.enabled} property provided.
+ */
+@Configuration
+@ConditionalOnClass(JmsConnectionFactory.class)
+@ConditionalOnResource(resources = "classpath:servicebusjms.enable.config")
+@ConditionalOnProperty(value = "spring.jms.servicebus.enabled", matchIfMissing = true)
+@EnableConfigurationProperties(AzureServiceBusJMSProperties.class)
+public class ServiceBusJMSAutoConfiguration {
+
+ private static final String AMQP_URI_FORMAT = "amqps://%s?amqp.idleTimeout=%d";
+
+ @Bean
+ @ConditionalOnMissingBean
+ public ConnectionFactory jmsConnectionFactory(AzureServiceBusJMSProperties serviceBusJMSProperties) {
+ final String connectionString = serviceBusJMSProperties.getConnectionString();
+ final String clientId = serviceBusJMSProperties.getTopicClientId();
+ final int idleTimeout = serviceBusJMSProperties.getIdleTimeout();
+
+ final ServiceBusKey serviceBusKey = ConnectionStringResolver.getServiceBusKey(connectionString);
+ final String host = serviceBusKey.getHost();
+ final String sasKeyName = serviceBusKey.getSharedAccessKeyName();
+ final String sasKey = serviceBusKey.getSharedAccessKey();
+
+ final String remoteUri = String.format(AMQP_URI_FORMAT, host, idleTimeout);
+ final JmsConnectionFactory jmsConnectionFactory = new JmsConnectionFactory();
+ jmsConnectionFactory.setRemoteURI(remoteUri);
+ jmsConnectionFactory.setClientID(clientId);
+ jmsConnectionFactory.setUsername(sasKeyName);
+ jmsConnectionFactory.setPassword(sasKey);
+ return new CachingConnectionFactory(jmsConnectionFactory);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public JmsTemplate jmsTemplate(ConnectionFactory jmsConnectionFactory) {
+ final JmsTemplate jmsTemplate = new JmsTemplate();
+ jmsTemplate.setConnectionFactory(jmsConnectionFactory);
+ return jmsTemplate;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public JmsListenerContainerFactory extends MessageListenerContainer> jmsListenerContainerFactory(
+ ConnectionFactory connectionFactory) {
+ final DefaultJmsListenerContainerFactory jmsListenerContainerFactory = new DefaultJmsListenerContainerFactory();
+ jmsListenerContainerFactory.setConnectionFactory(connectionFactory);
+ return jmsListenerContainerFactory;
+ }
+
+ @Bean
+ public JmsListenerContainerFactory extends MessageListenerContainer> topicJmsListenerContainerFactory(
+ ConnectionFactory connectionFactory) {
+ final DefaultJmsListenerContainerFactory jmsListenerContainerFactory = new DefaultJmsListenerContainerFactory();
+ jmsListenerContainerFactory.setConnectionFactory(connectionFactory);
+ jmsListenerContainerFactory.setSubscriptionDurable(Boolean.TRUE);
+ return jmsListenerContainerFactory;
+ }
+
+}
diff --git a/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/jms/ServiceBusKey.java b/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/jms/ServiceBusKey.java
new file mode 100644
index 000000000000..afb5dab0ecf0
--- /dev/null
+++ b/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/jms/ServiceBusKey.java
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.microsoft.azure.spring.autoconfigure.jms;
+
+/**
+ * POJO describes Service Bus connection info
+ */
+public class ServiceBusKey {
+ private final String host;
+ private final String sharedAccessKeyName;
+ private final String sharedAccessKey;
+
+ ServiceBusKey(String host, String sharedAccessKeyName, String sharedAccessKey) {
+ this.host = host;
+ this.sharedAccessKeyName = sharedAccessKeyName;
+ this.sharedAccessKey = sharedAccessKey;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public String getSharedAccessKeyName() {
+ return sharedAccessKeyName;
+ }
+
+ public String getSharedAccessKey() {
+ return sharedAccessKey;
+ }
+
+}
diff --git a/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorMetricsExportAutoConfiguration.java b/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorMetricsExportAutoConfiguration.java
new file mode 100644
index 000000000000..d008a19a4cf2
--- /dev/null
+++ b/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorMetricsExportAutoConfiguration.java
@@ -0,0 +1,76 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.microsoft.azure.spring.autoconfigure.metrics;
+
+import com.microsoft.applicationinsights.TelemetryConfiguration;
+import io.micrometer.azuremonitor.AzureMonitorConfig;
+import io.micrometer.azuremonitor.AzureMonitorMeterRegistry;
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.core.instrument.util.StringUtils;
+import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
+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.AutoConfigureBefore;
+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.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Auto-Configuration for exporting metrics to Azure Application Insights.
+ *
+ * @author Dhaval Doshi
+ */
+@Configuration
+@AutoConfigureBefore({CompositeMeterRegistryAutoConfiguration.class,
+ SimpleMetricsExportAutoConfiguration.class})
+@AutoConfigureAfter(MetricsAutoConfiguration.class)
+@ConditionalOnBean(Clock.class)
+@ConditionalOnClass(AzureMonitorMeterRegistry.class)
+@ConditionalOnResource(resources = "classpath:metrics.enable.config")
+@ConditionalOnProperty(prefix = "management.metrics.export.azuremonitor",
+ name = "enabled", havingValue = "true", matchIfMissing = true)
+@EnableConfigurationProperties(AzureMonitorProperties.class)
+public class AzureMonitorMetricsExportAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public AzureMonitorConfig azureConfig(AzureMonitorProperties properties) {
+ return new AzureMonitorPropertiesConfigAdapter(properties);
+ }
+
+ /**
+ * This bean is already available when the
+ * Azure Application Insights starter
+ * is present.
+ *
+ * @param config Azure monitor config
+ * @return telemetry configuration
+ */
+ @Bean
+ @ConditionalOnMissingBean
+ public TelemetryConfiguration telemetryConfiguration(AzureMonitorConfig config) {
+ // Gets the active instance of TelemetryConfiguration either created by starter or xml
+ final TelemetryConfiguration telemetryConfiguration = TelemetryConfiguration.getActive();
+ if (StringUtils.isEmpty(telemetryConfiguration.getInstrumentationKey())) {
+ telemetryConfiguration.setInstrumentationKey(config.instrumentationKey());
+ }
+ return telemetryConfiguration;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public AzureMonitorMeterRegistry azureMeterRegistry(AzureMonitorConfig config,
+ TelemetryConfiguration configuration, Clock clock) {
+ return AzureMonitorMeterRegistry.builder(config)
+ .clock(clock)
+ .telemetryConfiguration(configuration)
+ .build();
+ }
+}
diff --git a/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorProperties.java b/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorProperties.java
new file mode 100644
index 000000000000..3e288e01cf9f
--- /dev/null
+++ b/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorProperties.java
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.microsoft.azure.spring.autoconfigure.metrics;
+
+import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryProperties;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * {@link ConfigurationProperties} for configuring Azure Application Insights metrics export.
+ *
+ * @author Dhaval Doshi
+ */
+@ConfigurationProperties(prefix = "management.metrics.export.azuremonitor")
+public class AzureMonitorProperties extends StepRegistryProperties {
+ private String instrumentationKey;
+
+ public String getInstrumentationKey() {
+ return this.instrumentationKey;
+ }
+
+ public void setInstrumentationKey(String instrumentationKey) {
+ this.instrumentationKey = instrumentationKey;
+ }
+}
diff --git a/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorPropertiesConfigAdapter.java b/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorPropertiesConfigAdapter.java
new file mode 100644
index 000000000000..93646aadc7ed
--- /dev/null
+++ b/sdk/spring/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorPropertiesConfigAdapter.java
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.microsoft.azure.spring.autoconfigure.metrics;
+
+import io.micrometer.azuremonitor.AzureMonitorConfig;
+import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryPropertiesConfigAdapter;
+
+/**
+ * Adapter to convert {@link AzureMonitorProperties} to a {@link AzureMonitorConfig}.
+ *
+ * @author Dhaval Doshi
+ */
+public class AzureMonitorPropertiesConfigAdapter extends StepRegistryPropertiesConfigAdapter
+ implements AzureMonitorConfig {
+
+ AzureMonitorPropertiesConfigAdapter(AzureMonitorProperties properties) {
+ super(properties);
+ }
+
+ @Override
+ public String instrumentationKey() {
+ return get(AzureMonitorProperties::getInstrumentationKey, AzureMonitorConfig.super::instrumentationKey);
+ }
+}
diff --git a/sdk/spring/azure-spring-boot/src/test/java/com/microsoft/azure/spring/autoconfigure/jms/ConnectionStringResolverTest.java b/sdk/spring/azure-spring-boot/src/test/java/com/microsoft/azure/spring/autoconfigure/jms/ConnectionStringResolverTest.java
new file mode 100644
index 000000000000..d6eaa34ae05a
--- /dev/null
+++ b/sdk/spring/azure-spring-boot/src/test/java/com/microsoft/azure/spring/autoconfigure/jms/ConnectionStringResolverTest.java
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.microsoft.azure.spring.autoconfigure.jms;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ConnectionStringResolverTest {
+ @Test
+ public void testConnectionStringResolver() {
+ final String connectionString = "Endpoint=sb://host/;SharedAccessKeyName=sasKeyName;SharedAccessKey=sasKey";
+
+ final ServiceBusKey serviceBusKey = ConnectionStringResolver.getServiceBusKey(connectionString);
+ final String host = serviceBusKey.getHost();
+ final String sasKeyName = serviceBusKey.getSharedAccessKeyName();
+ final String sasKey = serviceBusKey.getSharedAccessKey();
+
+ Assert.assertEquals("host", host);
+ Assert.assertEquals("sasKeyName", sasKeyName);
+ Assert.assertEquals("sasKey", sasKey);
+ }
+}
diff --git a/sdk/spring/azure-spring-boot/src/test/java/com/microsoft/azure/spring/autoconfigure/jms/ServiceBusJMSAutoConfigurationTest.java b/sdk/spring/azure-spring-boot/src/test/java/com/microsoft/azure/spring/autoconfigure/jms/ServiceBusJMSAutoConfigurationTest.java
new file mode 100644
index 000000000000..20db17a65d59
--- /dev/null
+++ b/sdk/spring/azure-spring-boot/src/test/java/com/microsoft/azure/spring/autoconfigure/jms/ServiceBusJMSAutoConfigurationTest.java
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.microsoft.azure.spring.autoconfigure.jms;
+
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.junit.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.FilteredClassLoader;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ServiceBusJMSAutoConfigurationTest {
+ private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(ServiceBusJMSAutoConfiguration.class));
+
+ @Test
+ public void testAzureServiceBusDisabled() {
+ this.contextRunner.withPropertyValues("spring.jms.servicebus.enabled=false")
+ .run(context -> assertThat(context).doesNotHaveBean(AzureServiceBusJMSProperties.class));
+ }
+
+ @Test
+ public void testWithoutServiceBusJMSNamespace() {
+ this.contextRunner.withClassLoader(new FilteredClassLoader(JmsConnectionFactory.class))
+ .run(context -> assertThat(context).doesNotHaveBean(AzureServiceBusJMSProperties.class));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testAzureServiceBusJMSPropertiesValidation() {
+ this.contextRunner.run(context -> context.getBean(AzureServiceBusJMSProperties.class));
+ }
+
+ @Test
+ public void testAzureServiceBusJMSPropertiesConfigured() {
+
+ final String connectionString = "Endpoint=sb://host/;SharedAccessKeyName=sasKeyName;SharedAccessKey=sasKey";
+
+ this.contextRunner = this.contextRunner.withPropertyValues(
+ "spring.jms.servicebus.connection-string=" + connectionString
+ );
+
+ this.contextRunner = this.contextRunner.withPropertyValues(
+ "spring.jms.servicebus.topic-client-id=cid"
+ );
+
+ this.contextRunner = this.contextRunner.withPropertyValues(
+ "spring.jms.servicebus.idle-timeout=123"
+ );
+
+ this.contextRunner.run(
+ context -> {
+ assertThat(context).hasSingleBean(AzureServiceBusJMSProperties.class);
+ assertThat(context.getBean(AzureServiceBusJMSProperties.class).getConnectionString()).isEqualTo(
+ connectionString);
+ assertThat(context.getBean(AzureServiceBusJMSProperties.class).getTopicClientId()).isEqualTo("cid");
+ assertThat(context.getBean(AzureServiceBusJMSProperties.class).getIdleTimeout()).isEqualTo(123);
+ }
+ );
+ }
+
+}
diff --git a/sdk/spring/azure-spring-boot/src/test/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorMetricsExportAutoConfigurationTests.java b/sdk/spring/azure-spring-boot/src/test/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorMetricsExportAutoConfigurationTests.java
new file mode 100644
index 000000000000..5c3c1a198cf4
--- /dev/null
+++ b/sdk/spring/azure-spring-boot/src/test/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorMetricsExportAutoConfigurationTests.java
@@ -0,0 +1,158 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.microsoft.azure.spring.autoconfigure.metrics;
+
+import io.micrometer.azuremonitor.AzureMonitorConfig;
+import io.micrometer.azuremonitor.AzureMonitorMeterRegistry;
+import io.micrometer.core.instrument.Clock;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
+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.Import;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Tests for autoconfiguration of {@link AzureMonitorMetricsExportAutoConfiguration}
+ *
+ * @author Dhaval Doshi
+ */
+public class AzureMonitorMetricsExportAutoConfigurationTests {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations
+ .of(AzureMonitorMetricsExportAutoConfiguration.class));
+
+ @Test
+ public void backsOffWithoutAClock() {
+ this.contextRunner.run((context) -> assertThat(context)
+ .doesNotHaveBean(AzureMonitorMeterRegistry.class));
+ }
+
+ @Test
+ @Ignore("Somewhere in the class path there is xml from where the config is picked for AI")
+ public void failsWithoutAnApiKey() {
+ this.contextRunner.withUserConfiguration(BaseConfiguration.class)
+ .run((context) -> assertThat(context).hasFailed());
+ }
+
+ @Test
+ public void autoConfiguresConfigAndMeterRegistry() {
+ this.contextRunner.withUserConfiguration(BaseConfiguration.class)
+ .withPropertyValues(
+ "management.metrics.export.azuremonitor.instrumentation-key=fakekey")
+ .run((context) -> assertThat(context)
+ .hasSingleBean(AzureMonitorMeterRegistry.class)
+ .hasSingleBean(AzureMonitorConfig.class));
+ }
+
+ @Test
+ public void autoConfigurationCanBeDisabled() {
+ this.contextRunner.withUserConfiguration(BaseConfiguration.class)
+ .withPropertyValues(
+ "management.metrics.export.azuremonitor.enabled=false")
+ .run((context) -> assertThat(context)
+ .doesNotHaveBean(AzureMonitorMeterRegistry.class)
+ .doesNotHaveBean(AzureMonitorConfig.class));
+ }
+
+ @Test
+ public void allowsCustomConfigToBeUsed() {
+ this.contextRunner.withUserConfiguration(CustomConfigConfiguration.class)
+ .run((context) -> assertThat(context)
+ .hasSingleBean(AzureMonitorMeterRegistry.class)
+ .hasSingleBean(AzureMonitorConfig.class).hasBean("customConfig"));
+ }
+
+ @Test
+ public void allowsCustomRegistryToBeUsed() {
+ this.contextRunner.withUserConfiguration(CustomRegistryConfiguration.class)
+ .withPropertyValues(
+ "management.metrics.export.azuremonitor.instrumentation-key=fakekey")
+ .run((context) -> assertThat(context)
+ .hasSingleBean(AzureMonitorMeterRegistry.class)
+ .hasBean("customRegistry")
+ .hasSingleBean(AzureMonitorConfig.class));
+ }
+
+ @Test
+ public void stopsMeterRegistryWhenContextIsClosed() {
+ this.contextRunner.withUserConfiguration(BaseConfiguration.class)
+ .withPropertyValues(
+ "management.metrics.export.azuremonitor.instrumentation-key=fakekey")
+ .run((context) -> {
+ final AzureMonitorMeterRegistry registry = spyOnDisposableBean(
+ AzureMonitorMeterRegistry.class, context);
+ context.close();
+ verify(registry).stop();
+ });
+ }
+
+ @SuppressWarnings("unchecked")
+ private T spyOnDisposableBean(Class type,
+ AssertableApplicationContext context) {
+ final String[] names = context.getBeanNamesForType(type);
+ assertThat(names).hasSize(1);
+ final String registryBeanName = names[0];
+ final Map disposableBeans = (Map) ReflectionTestUtils
+ .getField(context.getAutowireCapableBeanFactory(), "disposableBeans");
+ final Object registryAdapter = disposableBeans.get(registryBeanName);
+ final T registry = (T) spy(ReflectionTestUtils.getField(registryAdapter, "bean"));
+ ReflectionTestUtils.setField(registryAdapter, "bean", registry);
+ return registry;
+ }
+
+ @Configuration
+ static class BaseConfiguration {
+
+ @Bean
+ public Clock clock() {
+ return Clock.SYSTEM;
+ }
+
+ }
+
+ @Configuration
+ @Import(BaseConfiguration.class)
+ static class CustomConfigConfiguration {
+
+ @Bean
+ public AzureMonitorConfig customConfig() {
+ return new AzureMonitorConfig() {
+
+ @Override
+ public String get(String k) {
+ if ("azuremonitor.instrumentation-key".equals(k)) {
+ return "12345";
+ }
+ return null;
+ }
+
+ };
+ }
+
+ }
+
+ @Configuration
+ @Import(BaseConfiguration.class)
+ static class CustomRegistryConfiguration {
+
+ @Bean
+ public AzureMonitorMeterRegistry customRegistry(AzureMonitorConfig config,
+ Clock clock) {
+ return AzureMonitorMeterRegistry.builder(config)
+ .clock(clock)
+ .build();
+ }
+ }
+}
diff --git a/sdk/spring/azure-spring-boot/src/test/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorPropertiesTest.java b/sdk/spring/azure-spring-boot/src/test/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorPropertiesTest.java
new file mode 100644
index 000000000000..f180bfe3152a
--- /dev/null
+++ b/sdk/spring/azure-spring-boot/src/test/java/com/microsoft/azure/spring/autoconfigure/metrics/AzureMonitorPropertiesTest.java
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.microsoft.azure.spring.autoconfigure.metrics;
+
+import io.micrometer.azuremonitor.AzureMonitorConfig;
+import io.micrometer.core.instrument.step.StepRegistryConfig;
+import org.junit.Test;
+import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryProperties;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link AzureMonitorProperties}.
+ *
+ * @author Dhaval Doshi
+ */
+
+public class AzureMonitorPropertiesTest {
+
+ @SuppressWarnings("depreciation")
+ private void assertStepRegistryDefaultValues(StepRegistryProperties properties,
+ StepRegistryConfig config) {
+ assertThat(properties.getStep()).isEqualTo(config.step());
+ assertThat(properties.isEnabled()).isEqualTo(config.enabled());
+ assertThat(properties.getConnectTimeout()).isEqualTo(config.connectTimeout());
+ assertThat(properties.getReadTimeout()).isEqualTo(config.readTimeout());
+ assertThat(properties.getNumThreads()).isEqualTo(config.numThreads());
+ assertThat(properties.getBatchSize()).isEqualTo(config.batchSize());
+ }
+
+ @Test
+ public void defaultValuesAreConsistent() {
+ final AzureMonitorProperties properties = new AzureMonitorProperties();
+ final AzureMonitorConfig config = (key) -> null;
+ assertStepRegistryDefaultValues(properties, config);
+ }
+
+}
diff --git a/sdk/spring/ci.yml b/sdk/spring/ci.yml
index 0fe9bd266f5c..084ee09aed6e 100644
--- a/sdk/spring/ci.yml
+++ b/sdk/spring/ci.yml
@@ -50,7 +50,12 @@ stages:
- name: azure-keyvault-secrets-spring-boot-starter
groupId: com.microsoft.azure
safeName: azurespringbootstarterkeyvaultsecrets
-
+ - name: azure-spring-boot-metrics-starter
+ groupId: com.microsoft.azure
+ safeName: azurespringbootstartermetrics
+ - name: azure-servicebus-jms-spring-boot-starter
+ groupId: com.microsoft.azure
+ safeName: azurespringbootstarterservicebusjms
diff --git a/sdk/spring/pom.xml b/sdk/spring/pom.xml
index d251259a85ad..2c21d69c6f93 100644
--- a/sdk/spring/pom.xml
+++ b/sdk/spring/pom.xml
@@ -13,6 +13,8 @@
azure-spring-boot-starter
azure-spring-boot-starter-active-directory
azure-spring-boot-starter-keyvault-secrets
+ azure-spring-boot-starter-metrics
+ azure-spring-boot-starter-servicebus-jms