Use spring.application.name for OTel service.name when not set

Closes gh-37285
This commit is contained in:
Moritz Halbritter
2023-09-11 10:38:51 +02:00
parent 11ebe32dcf
commit fa42316652
3 changed files with 59 additions and 18 deletions

View File

@@ -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

View File

@@ -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<OtlpProperties> 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<Ot
@Override
@SuppressWarnings("removal")
public Map<String, String> resourceAttributes() {
Map<String, String> 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

View File

@@ -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);
}
}