From fa423166520820047aeaf89d7ed068d1ef9ed12a Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Mon, 11 Sep 2023 10:38:51 +0200 Subject: [PATCH] Use spring.application.name for OTel service.name when not set Closes gh-37285 --- .../OtlpMetricsExportAutoConfiguration.java | 16 ++------ .../otlp/OtlpPropertiesConfigAdapter.java | 24 ++++++++++-- .../OtlpPropertiesConfigAdapterTests.java | 37 +++++++++++++++++-- 3 files changed, 59 insertions(+), 18 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpMetricsExportAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpMetricsExportAutoConfiguration.java index 5ee64e539e..27e974bab8 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpMetricsExportAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpMetricsExportAutoConfiguration.java @@ -32,6 +32,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.core.env.Environment; /** * {@link EnableAutoConfiguration Auto-configuration} for exporting metrics to OTLP. @@ -49,20 +50,11 @@ import org.springframework.context.annotation.Bean; @EnableConfigurationProperties({ OtlpProperties.class, OpenTelemetryProperties.class }) public class OtlpMetricsExportAutoConfiguration { - private final OtlpProperties properties; - - private final OpenTelemetryProperties openTelemetryProperties; - - public OtlpMetricsExportAutoConfiguration(OtlpProperties properties, - OpenTelemetryProperties openTelemetryProperties) { - this.properties = properties; - this.openTelemetryProperties = openTelemetryProperties; - } - @Bean @ConditionalOnMissingBean - public OtlpConfig otlpConfig() { - return new OtlpPropertiesConfigAdapter(this.properties, this.openTelemetryProperties); + OtlpConfig otlpConfig(OtlpProperties properties, OpenTelemetryProperties openTelemetryProperties, + Environment environment) { + return new OtlpPropertiesConfigAdapter(properties, openTelemetryProperties, environment); } @Bean diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpPropertiesConfigAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpPropertiesConfigAdapter.java index ebf406f30f..f8dd3c5bb2 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpPropertiesConfigAdapter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpPropertiesConfigAdapter.java @@ -16,6 +16,8 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.otlp; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -24,6 +26,7 @@ import io.micrometer.registry.otlp.OtlpConfig; import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryPropertiesConfigAdapter; import org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryProperties; +import org.springframework.core.env.Environment; import org.springframework.util.CollectionUtils; /** @@ -35,11 +38,20 @@ import org.springframework.util.CollectionUtils; */ class OtlpPropertiesConfigAdapter extends StepRegistryPropertiesConfigAdapter implements OtlpConfig { + /** + * Default value for application name if {@code spring.application.name} is not set. + */ + private static final String DEFAULT_APPLICATION_NAME = "application"; + private final OpenTelemetryProperties openTelemetryProperties; - OtlpPropertiesConfigAdapter(OtlpProperties properties, OpenTelemetryProperties openTelemetryProperties) { + private final Environment environment; + + OtlpPropertiesConfigAdapter(OtlpProperties properties, OpenTelemetryProperties openTelemetryProperties, + Environment environment) { super(properties); this.openTelemetryProperties = openTelemetryProperties; + this.environment = environment; } @Override @@ -60,10 +72,16 @@ class OtlpPropertiesConfigAdapter extends StepRegistryPropertiesConfigAdapter resourceAttributes() { + Map result; if (!CollectionUtils.isEmpty(this.openTelemetryProperties.getResourceAttributes())) { - return this.openTelemetryProperties.getResourceAttributes(); + result = new HashMap<>(this.openTelemetryProperties.getResourceAttributes()); } - return get(OtlpProperties::getResourceAttributes, OtlpConfig.super::resourceAttributes); + else { + result = new HashMap<>(get(OtlpProperties::getResourceAttributes, OtlpConfig.super::resourceAttributes)); + } + result.computeIfAbsent("service.name", + (ignore) -> this.environment.getProperty("spring.application.name", DEFAULT_APPLICATION_NAME)); + return Collections.unmodifiableMap(result); } @Override diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpPropertiesConfigAdapterTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpPropertiesConfigAdapterTests.java index 27bd22ccb7..8d736bca0e 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpPropertiesConfigAdapterTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpPropertiesConfigAdapterTests.java @@ -25,6 +25,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryProperties; +import org.springframework.mock.env.MockEnvironment; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; @@ -41,10 +42,13 @@ class OtlpPropertiesConfigAdapterTests { private OpenTelemetryProperties openTelemetryProperties; + private MockEnvironment environment; + @BeforeEach void setUp() { this.properties = new OtlpProperties(); this.openTelemetryProperties = new OpenTelemetryProperties(); + this.environment = new MockEnvironment(); } @Test @@ -93,7 +97,8 @@ class OtlpPropertiesConfigAdapterTests { void openTelemetryPropertiesShouldOverrideOtlpPropertiesIfNotEmpty() { this.properties.setResourceAttributes(Map.of("a", "alpha")); this.openTelemetryProperties.setResourceAttributes(Map.of("b", "beta")); - assertThat(createAdapter().resourceAttributes()).containsExactly(entry("b", "beta")); + assertThat(createAdapter().resourceAttributes()).contains(entry("b", "beta")); + assertThat(createAdapter().resourceAttributes()).doesNotContain(entry("a", "alpha")); } @Test @@ -101,11 +106,37 @@ class OtlpPropertiesConfigAdapterTests { void openTelemetryPropertiesShouldNotOverrideOtlpPropertiesIfEmpty() { this.properties.setResourceAttributes(Map.of("a", "alpha")); this.openTelemetryProperties.setResourceAttributes(Collections.emptyMap()); - assertThat(createAdapter().resourceAttributes()).containsExactly(entry("a", "alpha")); + assertThat(createAdapter().resourceAttributes()).contains(entry("a", "alpha")); + } + + @Test + @SuppressWarnings("removal") + void serviceNameOverridesApplicationName() { + this.environment.setProperty("spring.application.name", "alpha"); + this.properties.setResourceAttributes(Map.of("service.name", "beta")); + assertThat(createAdapter().resourceAttributes()).containsEntry("service.name", "beta"); + } + + @Test + void serviceNameOverridesApplicationNameWhenUsingOtelProperties() { + this.environment.setProperty("spring.application.name", "alpha"); + this.openTelemetryProperties.setResourceAttributes(Map.of("service.name", "beta")); + assertThat(createAdapter().resourceAttributes()).containsEntry("service.name", "beta"); + } + + @Test + void shouldUseApplicationNameIfServiceNameIsNotSet() { + this.environment.setProperty("spring.application.name", "alpha"); + assertThat(createAdapter().resourceAttributes()).containsEntry("service.name", "alpha"); + } + + @Test + void shouldUseDefaultApplicationNameIfApplicationNameIsNotSet() { + assertThat(createAdapter().resourceAttributes()).containsEntry("service.name", "application"); } private OtlpPropertiesConfigAdapter createAdapter() { - return new OtlpPropertiesConfigAdapter(this.properties, this.openTelemetryProperties); + return new OtlpPropertiesConfigAdapter(this.properties, this.openTelemetryProperties, this.environment); } }