From a50d1f0bd64186197beca3306fefafff8ae57234 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 16 Nov 2022 16:28:08 -0800 Subject: [PATCH 1/3] Switch to use BeanUtils.getPropertyDescriptors Update `BindableRuntimeHintsRegistrar` to use `BeanUtils.getPropertyDescriptors` rather than `BeanInfoFactory`. Closes gh-33232 --- .../bind/BindableRuntimeHintsRegistrar.java | 30 ++++--------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/BindableRuntimeHintsRegistrar.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/BindableRuntimeHintsRegistrar.java index b0b7154a6490..69ec3bb95e6e 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/BindableRuntimeHintsRegistrar.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/BindableRuntimeHintsRegistrar.java @@ -16,9 +16,6 @@ package org.springframework.boot.context.properties.bind; -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -34,14 +31,14 @@ import org.springframework.aot.hint.ReflectionHints; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; -import org.springframework.beans.BeanInfoFactory; -import org.springframework.beans.ExtendedBeanInfoFactory; +import org.springframework.beans.BeanUtils; import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.ResolvableType; import org.springframework.core.StandardReflectionParameterNameDiscoverer; import org.springframework.core.annotation.MergedAnnotations; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; /** @@ -59,8 +56,6 @@ */ public class BindableRuntimeHintsRegistrar implements RuntimeHintsRegistrar { - private static final BeanInfoFactory beanInfoFactory = new ExtendedBeanInfoFactory(); - private final Class[] types; /** @@ -120,7 +115,7 @@ private final class Processor { private final Constructor bindConstructor; - private final BeanInfo beanInfo; + private final PropertyDescriptor[] propertyDescriptors; private final Set> seen; @@ -134,24 +129,11 @@ private Processor(Class type, boolean nestedType, Set> seen, Set> compiledWithoutParameters) { this.type = type; this.bindConstructor = BindConstructorProvider.DEFAULT.getBindConstructor(Bindable.of(type), nestedType); - this.beanInfo = getBeanInfo(type); + this.propertyDescriptors = BeanUtils.getPropertyDescriptors(type); this.seen = seen; this.compiledWithoutParameters = compiledWithoutParameters; } - private static BeanInfo getBeanInfo(Class beanType) { - try { - BeanInfo beanInfo = beanInfoFactory.getBeanInfo(beanType); - if (beanInfo != null) { - return beanInfo; - } - return Introspector.getBeanInfo(beanType, Introspector.IGNORE_ALL_BEANINFO); - } - catch (IntrospectionException ex) { - return null; - } - } - void process(ReflectionHints hints) { if (this.seen.contains(this.type)) { return; @@ -161,7 +143,7 @@ void process(ReflectionHints hints) { if (this.bindConstructor != null) { handleValueObjectProperties(hints); } - else if (this.beanInfo != null) { + else if (!ObjectUtils.isEmpty(this.propertyDescriptors)) { handleJavaBeanProperties(hints); } } @@ -196,7 +178,7 @@ private void handleValueObjectProperties(ReflectionHints hints) { } private void handleJavaBeanProperties(ReflectionHints hints) { - for (PropertyDescriptor propertyDescriptor : this.beanInfo.getPropertyDescriptors()) { + for (PropertyDescriptor propertyDescriptor : this.propertyDescriptors) { Method writeMethod = propertyDescriptor.getWriteMethod(); if (writeMethod != null) { hints.registerMethod(writeMethod, ExecutableMode.INVOKE); From 42bb4c06152040711733aa58a862395abbe8d43c Mon Sep 17 00:00:00 2001 From: Glenn Oppegard Date: Fri, 21 Oct 2022 13:43:45 -0600 Subject: [PATCH 2/3] Align Wavefront application tags support with Spring Boot 2.x Update `application-name` and `service-name` `management.wavefront` properties to align with Spring Boot 2.x support. The properties now use the wavefront terminology where `application` refers to an a collection of (micro)`services`. This commit also adds `cluster-name` and `shard-name` properties that can be used to add additional items to the `ApplicationTags`. See gh-32844 --- ...vefrontMetricsExportAutoConfiguration.java | 19 ++++++++ .../WavefrontTracingAutoConfiguration.java | 36 +++++++++++--- .../wavefront/WavefrontProperties.java | 48 ++++++++++++++++++- ...ntMetricsExportAutoConfigurationTests.java | 23 +++++++++ ...avefrontTracingAutoConfigurationTests.java | 27 +++++++++-- 5 files changed, 140 insertions(+), 13 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java index 470d4f919aa1..883a80044bfa 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java @@ -16,12 +16,18 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront; +import java.util.Map; + import com.wavefront.sdk.common.WavefrontSender; +import com.wavefront.sdk.common.application.ApplicationTags; import io.micrometer.core.instrument.Clock; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; import io.micrometer.wavefront.WavefrontConfig; import io.micrometer.wavefront.WavefrontMeterRegistry; import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer; import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.export.ConditionalOnEnabledMetricsExport; import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration; @@ -42,6 +48,7 @@ * @author Jon Schneider * @author Artsiom Yudovin * @author Stephane Nicoll + * @author Glenn Oppegard * @since 2.0.0 */ @AutoConfiguration( @@ -68,4 +75,16 @@ public WavefrontMeterRegistry wavefrontMeterRegistry(WavefrontConfig wavefrontCo return WavefrontMeterRegistry.builder(wavefrontConfig).clock(clock).wavefrontSender(wavefrontSender).build(); } + @Bean + @ConditionalOnBean(ApplicationTags.class) + MeterRegistryCustomizer applicationTagsCustomizer(ApplicationTags applicationTags) { + Tags commonTags = Tags.of(applicationTags.toPointTags().entrySet().stream() + .map(WavefrontMetricsExportAutoConfiguration::asTag).toList()); + return (registry) -> registry.config().commonTags(commonTags); + } + + private static Tag asTag(Map.Entry entry) { + return Tag.of(entry.getKey(), entry.getValue()); + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/WavefrontTracingAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/WavefrontTracingAutoConfiguration.java index 4b86760af224..8fad8a8fd7bd 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/WavefrontTracingAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/WavefrontTracingAutoConfiguration.java @@ -49,6 +49,7 @@ * {@link EnableAutoConfiguration Auto-configuration} for Wavefront tracing. * * @author Moritz Halbritter + * @author Glenn Oppegard * @since 3.0.0 */ @AutoConfiguration(after = { MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class }) @@ -59,19 +60,40 @@ public class WavefrontTracingAutoConfiguration { /** - * Default value for application name if {@code spring.application.name} is not set. + * Default value for the Wavefront Application name. + * @see Wavefront + * Application Tags */ - private static final String DEFAULT_APPLICATION_NAME = "application"; + private static final String DEFAULT_WAVEFRONT_APPLICATION_NAME = "unnamed_application"; + + /** + * Default value for the Wavefront Service name if {@code spring.application.name} is + * not set. + * @see Wavefront + * Application Tags + */ + private static final String DEFAULT_WAVEFRONT_SERVICE_NAME = "unnamed_service"; @Bean @ConditionalOnMissingBean public ApplicationTags applicationTags(Environment environment, WavefrontProperties properties) { - String springApplicationName = environment.getProperty("spring.application.name", DEFAULT_APPLICATION_NAME); + String fallbackWavefrontServiceName = environment.getProperty("spring.application.name", + DEFAULT_WAVEFRONT_SERVICE_NAME); Tracing tracing = properties.getTracing(); - String applicationName = (tracing.getApplicationName() != null) ? tracing.getApplicationName() - : springApplicationName; - String serviceName = (tracing.getServiceName() != null) ? tracing.getServiceName() : springApplicationName; - return new ApplicationTags.Builder(applicationName, serviceName).build(); + String wavefrontServiceName = (tracing.getServiceName() != null) ? tracing.getServiceName() + : fallbackWavefrontServiceName; + String wavefrontApplicationName = (tracing.getApplicationName() != null) ? tracing.getApplicationName() + : DEFAULT_WAVEFRONT_APPLICATION_NAME; + ApplicationTags.Builder builder = new ApplicationTags.Builder(wavefrontApplicationName, wavefrontServiceName); + if (tracing.getClusterName() != null) { + builder.cluster(tracing.getClusterName()); + } + if (tracing.getShardName() != null) { + builder.shard(tracing.getShardName()); + } + return builder.build(); } @Configuration(proxyBeanMethods = false) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontProperties.java index 37a963d62466..741a7438f8bc 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontProperties.java @@ -21,6 +21,8 @@ import java.net.UnknownHostException; import java.time.Duration; +import com.wavefront.sdk.common.application.ApplicationTags; + import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.PushRegistryProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException; @@ -30,6 +32,7 @@ * Configuration properties to configure Wavefront. * * @author Moritz Halbritter + * @author Glenn Oppegard * @since 3.0.0 */ @ConfigurationProperties(prefix = "management.wavefront") @@ -261,15 +264,40 @@ public void setBatchSize(Integer batchSize) { public static class Tracing { /** - * Application name. Defaults to 'spring.application.name'. + * Wavefront Application name used in {@link ApplicationTags}. Defaults to + * 'unnamed_application'. + * @see Wavefront + * Application Tags */ private String applicationName; /** - * Service name. Defaults to 'spring.application.name'. + * Wavefront Service name used in {@link ApplicationTags}, falling back to + * {@code spring.application.name}. If both are unset it defaults to + * 'unnamed_service'. + * @see Wavefront + * Application Tags */ private String serviceName; + /** + * Optional Wavefront Cluster name used in {@link ApplicationTags}. + * @see Wavefront + * Application Tags + */ + private String clusterName; + + /** + * Optional Wavefront Shard name used in {@link ApplicationTags}. + * @see Wavefront + * Application Tags + */ + private String shardName; + public String getServiceName() { return this.serviceName; } @@ -286,6 +314,22 @@ public void setApplicationName(String applicationName) { this.applicationName = applicationName; } + public String getClusterName() { + return this.clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public String getShardName() { + return this.shardName; + } + + public void setShardName(String shardName) { + this.shardName = shardName; + } + } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java index d8901202f041..449266c3f2c2 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java @@ -16,12 +16,16 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront; +import java.util.Map; + import com.wavefront.sdk.common.WavefrontSender; +import com.wavefront.sdk.common.application.ApplicationTags; import io.micrometer.core.instrument.Clock; import io.micrometer.wavefront.WavefrontConfig; import io.micrometer.wavefront.WavefrontMeterRegistry; import org.junit.jupiter.api.Test; +import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; @@ -36,6 +40,7 @@ * * @author Jon Schneider * @author Stephane Nicoll + * @author Glenn Oppegard */ class WavefrontMetricsExportAutoConfigurationTests { @@ -81,6 +86,24 @@ void allowsRegistryToBeCustomized() { .hasSingleBean(WavefrontMeterRegistry.class).hasBean("customRegistry")); } + @Test + void exportsApplicationTagsInWavefrontRegistry() { + ApplicationTags.Builder appTagsBuilder = new ApplicationTags.Builder("super-application", "super-service"); + appTagsBuilder.cluster("super-cluster"); + appTagsBuilder.shard("super-shard"); + appTagsBuilder.customTags(Map.of("custom-key", "custom-val")); + + this.contextRunner.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class)) + .withUserConfiguration(BaseConfiguration.class).withBean(ApplicationTags.class, appTagsBuilder::build) + .run((context) -> { + WavefrontMeterRegistry registry = context.getBean(WavefrontMeterRegistry.class); + registry.counter("my.counter", "env", "qa"); + assertThat(registry.find("my.counter").tags("env", "qa").tags("application", "super-application") + .tags("service", "super-service").tags("cluster", "super-cluster") + .tags("shard", "super-shard").tags("custom-key", "custom-val").counter()).isNotNull(); + }); + } + @Test void stopsMeterRegistryWhenContextIsClosed() { this.contextRunner.withUserConfiguration(BaseConfiguration.class) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/WavefrontTracingAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/WavefrontTracingAutoConfigurationTests.java index 2999861b24bd..c4926b7e955b 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/WavefrontTracingAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/WavefrontTracingAutoConfigurationTests.java @@ -39,6 +39,7 @@ * Tests for {@link WavefrontTracingAutoConfiguration}. * * @author Moritz Halbritter + * @author Glenn Oppegard */ class WavefrontTracingAutoConfigurationTests { @@ -114,22 +115,40 @@ void shouldNotSupplyWavefrontOtelSpanExporterIfOtelIsMissing() { } @Test - void shouldHaveADefaultApplicationName() { + void shouldHaveADefaultApplicationNameAndServiceName() { this.contextRunner.withUserConfiguration(WavefrontSenderConfiguration.class).run((context) -> { ApplicationTags applicationTags = context.getBean(ApplicationTags.class); - assertThat(applicationTags.getApplication()).isEqualTo("application"); + assertThat(applicationTags.getApplication()).isEqualTo("unnamed_application"); + assertThat(applicationTags.getService()).isEqualTo("unnamed_service"); + assertThat(applicationTags.getCluster()).isNull(); + assertThat(applicationTags.getShard()).isNull(); }); } + @Test + void shouldUseSpringApplicationNameForServiceName() { + this.contextRunner.withUserConfiguration(WavefrontSenderConfiguration.class) + .withPropertyValues("spring.application.name=super-service").run((context) -> { + ApplicationTags applicationTags = context.getBean(ApplicationTags.class); + assertThat(applicationTags.getApplication()).isEqualTo("unnamed_application"); + assertThat(applicationTags.getService()).isEqualTo("super-service"); + }); + } + @Test void shouldHonorConfigProperties() { this.contextRunner.withUserConfiguration(WavefrontSenderConfiguration.class) - .withPropertyValues("spring.application.name=super-application", - "management.wavefront.tracing.service-name=super-service") + .withPropertyValues("spring.application.name=ignored", + "management.wavefront.tracing.application-name=super-application", + "management.wavefront.tracing.service-name=super-service", + "management.wavefront.tracing.cluster-name=super-cluster", + "management.wavefront.tracing.shard-name=super-shard") .run((context) -> { ApplicationTags applicationTags = context.getBean(ApplicationTags.class); assertThat(applicationTags.getApplication()).isEqualTo("super-application"); assertThat(applicationTags.getService()).isEqualTo("super-service"); + assertThat(applicationTags.getCluster()).isEqualTo("super-cluster"); + assertThat(applicationTags.getShard()).isEqualTo("super-shard"); }); } From a0f39d66feae7b03b5a6266cd37159672ca5fbdf Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 16 Nov 2022 16:49:38 -0800 Subject: [PATCH 3/3] Polish 'Align Wavefront application tags support with Spring Boot 2.x' See gh-32844 --- ...vefrontMetricsExportAutoConfiguration.java | 8 ++--- .../WavefrontTracingAutoConfiguration.java | 31 ++++++++++--------- .../wavefront/WavefrontProperties.java | 25 +++------------ ...ntMetricsExportAutoConfigurationTests.java | 11 +++---- 4 files changed, 30 insertions(+), 45 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java index 883a80044bfa..4204950b7222 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java @@ -77,13 +77,13 @@ public WavefrontMeterRegistry wavefrontMeterRegistry(WavefrontConfig wavefrontCo @Bean @ConditionalOnBean(ApplicationTags.class) - MeterRegistryCustomizer applicationTagsCustomizer(ApplicationTags applicationTags) { - Tags commonTags = Tags.of(applicationTags.toPointTags().entrySet().stream() - .map(WavefrontMetricsExportAutoConfiguration::asTag).toList()); + MeterRegistryCustomizer wavefrontApplicationTagsCustomizer( + ApplicationTags wavefrontApplicationTags) { + Tags commonTags = Tags.of(wavefrontApplicationTags.toPointTags().entrySet().stream().map(this::asTag).toList()); return (registry) -> registry.config().commonTags(commonTags); } - private static Tag asTag(Map.Entry entry) { + private Tag asTag(Map.Entry entry) { return Tag.of(entry.getKey(), entry.getValue()); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/WavefrontTracingAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/WavefrontTracingAutoConfiguration.java index 8fad8a8fd7bd..a07fb4217d95 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/WavefrontTracingAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/WavefrontTracingAutoConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.boot.actuate.autoconfigure.tracing.wavefront; import java.util.Collections; +import java.util.function.Supplier; import brave.handler.SpanHandler; import com.wavefront.sdk.common.WavefrontSender; @@ -40,10 +41,12 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.env.Environment; +import org.springframework.util.StringUtils; /** * {@link EnableAutoConfiguration Auto-configuration} for Wavefront tracing. @@ -65,7 +68,7 @@ public class WavefrontTracingAutoConfiguration { * "https://docs.wavefront.com/trace_data_details.html#application-tags">Wavefront * Application Tags */ - private static final String DEFAULT_WAVEFRONT_APPLICATION_NAME = "unnamed_application"; + private static final String DEFAULT_APPLICATION_NAME = "unnamed_application"; /** * Default value for the Wavefront Service name if {@code spring.application.name} is @@ -74,28 +77,26 @@ public class WavefrontTracingAutoConfiguration { * "https://docs.wavefront.com/trace_data_details.html#application-tags">Wavefront * Application Tags */ - private static final String DEFAULT_WAVEFRONT_SERVICE_NAME = "unnamed_service"; + private static final String DEFAULT_SERVICE_NAME = "unnamed_service"; @Bean @ConditionalOnMissingBean - public ApplicationTags applicationTags(Environment environment, WavefrontProperties properties) { - String fallbackWavefrontServiceName = environment.getProperty("spring.application.name", - DEFAULT_WAVEFRONT_SERVICE_NAME); + public ApplicationTags wavefrontApplicationTags(Environment environment, WavefrontProperties properties) { Tracing tracing = properties.getTracing(); - String wavefrontServiceName = (tracing.getServiceName() != null) ? tracing.getServiceName() - : fallbackWavefrontServiceName; - String wavefrontApplicationName = (tracing.getApplicationName() != null) ? tracing.getApplicationName() - : DEFAULT_WAVEFRONT_APPLICATION_NAME; + String wavefrontServiceName = getName(tracing.getServiceName(), + () -> environment.getProperty("spring.application.name", DEFAULT_SERVICE_NAME)); + String wavefrontApplicationName = getName(tracing.getApplicationName(), () -> DEFAULT_APPLICATION_NAME); + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); ApplicationTags.Builder builder = new ApplicationTags.Builder(wavefrontApplicationName, wavefrontServiceName); - if (tracing.getClusterName() != null) { - builder.cluster(tracing.getClusterName()); - } - if (tracing.getShardName() != null) { - builder.shard(tracing.getShardName()); - } + map.from(tracing::getClusterName).to(builder::cluster); + map.from(tracing::getShardName).to(builder::shard); return builder.build(); } + private String getName(String value, Supplier fallback) { + return (StringUtils.hasText(value)) ? value : fallback.get(); + } + @Configuration(proxyBeanMethods = false) @ConditionalOnClass(WavefrontSpanHandler.class) static class WavefrontMicrometer { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontProperties.java index 741a7438f8bc..4d8fac75fa33 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontProperties.java @@ -21,8 +21,6 @@ import java.net.UnknownHostException; import java.time.Duration; -import com.wavefront.sdk.common.application.ApplicationTags; - import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.PushRegistryProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException; @@ -264,37 +262,24 @@ public void setBatchSize(Integer batchSize) { public static class Tracing { /** - * Wavefront Application name used in {@link ApplicationTags}. Defaults to + * Wavefront Application name used in ApplicationTags. Defaults to * 'unnamed_application'. - * @see Wavefront - * Application Tags */ private String applicationName; /** - * Wavefront Service name used in {@link ApplicationTags}, falling back to - * {@code spring.application.name}. If both are unset it defaults to - * 'unnamed_service'. - * @see Wavefront - * Application Tags + * Wavefront Service name used in ApplicationTags, falling back to + * 'spring.application.name'. If both are unset it defaults to 'unnamed_service'. */ private String serviceName; /** - * Optional Wavefront Cluster name used in {@link ApplicationTags}. - * @see Wavefront - * Application Tags + * Optional Wavefront Cluster name used in ApplicationTags. */ private String clusterName; /** - * Optional Wavefront Shard name used in {@link ApplicationTags}. - * @see Wavefront - * Application Tags + * Optional Wavefront Shard name used in ApplicationTags. */ private String shardName; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java index 449266c3f2c2..28efcc5463ab 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java @@ -88,13 +88,12 @@ void allowsRegistryToBeCustomized() { @Test void exportsApplicationTagsInWavefrontRegistry() { - ApplicationTags.Builder appTagsBuilder = new ApplicationTags.Builder("super-application", "super-service"); - appTagsBuilder.cluster("super-cluster"); - appTagsBuilder.shard("super-shard"); - appTagsBuilder.customTags(Map.of("custom-key", "custom-val")); - + ApplicationTags.Builder builder = new ApplicationTags.Builder("super-application", "super-service"); + builder.cluster("super-cluster"); + builder.shard("super-shard"); + builder.customTags(Map.of("custom-key", "custom-val")); this.contextRunner.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class)) - .withUserConfiguration(BaseConfiguration.class).withBean(ApplicationTags.class, appTagsBuilder::build) + .withUserConfiguration(BaseConfiguration.class).withBean(ApplicationTags.class, builder::build) .run((context) -> { WavefrontMeterRegistry registry = context.getBean(WavefrontMeterRegistry.class); registry.counter("my.counter", "env", "qa");