diff --git a/module/spring-boot-micrometer-tracing-brave/src/main/java/org/springframework/boot/micrometer/tracing/brave/autoconfigure/BravePropagationConfigurations.java b/module/spring-boot-micrometer-tracing-brave/src/main/java/org/springframework/boot/micrometer/tracing/brave/autoconfigure/BravePropagationConfigurations.java index 626a28beb65d..4476800596f0 100644 --- a/module/spring-boot-micrometer-tracing-brave/src/main/java/org/springframework/boot/micrometer/tracing/brave/autoconfigure/BravePropagationConfigurations.java +++ b/module/spring-boot-micrometer-tracing-brave/src/main/java/org/springframework/boot/micrometer/tracing/brave/autoconfigure/BravePropagationConfigurations.java @@ -19,6 +19,7 @@ import java.util.List; import brave.baggage.BaggageField; +import brave.baggage.BaggageFields; import brave.baggage.BaggagePropagation; import brave.baggage.BaggagePropagation.FactoryBuilder; import brave.baggage.BaggagePropagationConfig; @@ -40,6 +41,7 @@ import org.springframework.boot.micrometer.tracing.autoconfigure.ConditionalOnEnabledTracingExport; import org.springframework.boot.micrometer.tracing.autoconfigure.TracingProperties; import org.springframework.boot.micrometer.tracing.autoconfigure.TracingProperties.Baggage.Correlation; +import org.springframework.boot.micrometer.tracing.autoconfigure.TracingProperties.Mdc; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @@ -138,7 +140,15 @@ Factory propagationFactory(BaggagePropagation.FactoryBuilder factoryBuilder) { @ConditionalOnMissingBean CorrelationScopeDecorator.Builder mdcCorrelationScopeDecoratorBuilder( ObjectProvider correlationScopeCustomizers) { - CorrelationScopeDecorator.Builder builder = MDCScopeDecorator.newBuilder(); + Mdc mdc = this.tracingProperties.getMdc(); + CorrelationScopeDecorator.Builder builder = MDCScopeDecorator.newBuilder() + // Clear existing traceId/spanId backage field mappings + // so the MDC key names can be customized below. + // BravePropagationConfigurationsTests validates the assumption that + // the builder only configures the trace/span id by default. + .clear() + .add(SingleCorrelationField.newBuilder(BaggageFields.TRACE_ID).name(mdc.getTraceIdKey()).build()) + .add(SingleCorrelationField.newBuilder(BaggageFields.SPAN_ID).name(mdc.getSpanIdKey()).build()); correlationScopeCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); return builder; } diff --git a/module/spring-boot-micrometer-tracing-brave/src/test/java/org/springframework/boot/micrometer/tracing/brave/autoconfigure/BraveAutoConfigurationTests.java b/module/spring-boot-micrometer-tracing-brave/src/test/java/org/springframework/boot/micrometer/tracing/brave/autoconfigure/BraveAutoConfigurationTests.java index e3daafbd45df..a121b3c08576 100644 --- a/module/spring-boot-micrometer-tracing-brave/src/test/java/org/springframework/boot/micrometer/tracing/brave/autoconfigure/BraveAutoConfigurationTests.java +++ b/module/spring-boot-micrometer-tracing-brave/src/test/java/org/springframework/boot/micrometer/tracing/brave/autoconfigure/BraveAutoConfigurationTests.java @@ -258,6 +258,31 @@ void shouldSupplyMdcCorrelationScopeDecoratorIfBaggageCorrelationDisabled() { .run((context) -> assertThat(context).hasBean("mdcCorrelationScopeDecoratorBuilder")); } + @Test + void correlationScopeDecoratorUsesDefaultMdcKeys() { + this.contextRunner.run((context) -> { + ScopeDecorator scopeDecorator = context.getBean(ScopeDecorator.class); + assertThat(scopeDecorator) + .extracting("fields", InstanceOfAssertFactories.array(SingleCorrelationField[].class)) + .extracting(SingleCorrelationField::name) + .containsExactly("traceId", "spanId"); + }); + } + + @Test + void correlationScopeDecoratorUsesCustomMdcKeys() { + this.contextRunner + .withPropertyValues("management.tracing.mdc.trace-id-key=customTraceId", + "management.tracing.mdc.span-id-key=customSpanId") + .run((context) -> { + ScopeDecorator scopeDecorator = context.getBean(ScopeDecorator.class); + assertThat(scopeDecorator) + .extracting("fields", InstanceOfAssertFactories.array(SingleCorrelationField[].class)) + .extracting(SingleCorrelationField::name) + .containsExactly("customTraceId", "customSpanId"); + }); + } + @Test void shouldHave128BitTraceId() { this.contextRunner.run((context) -> { diff --git a/module/spring-boot-micrometer-tracing-brave/src/test/java/org/springframework/boot/micrometer/tracing/brave/autoconfigure/BravePropagationConfigurationsTests.java b/module/spring-boot-micrometer-tracing-brave/src/test/java/org/springframework/boot/micrometer/tracing/brave/autoconfigure/BravePropagationConfigurationsTests.java new file mode 100644 index 000000000000..44c7ae203258 --- /dev/null +++ b/module/spring-boot-micrometer-tracing-brave/src/test/java/org/springframework/boot/micrometer/tracing/brave/autoconfigure/BravePropagationConfigurationsTests.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012-present 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.micrometer.tracing.brave.autoconfigure; + +import brave.baggage.BaggageFields; +import brave.baggage.CorrelationScopeConfig.SingleCorrelationField; +import brave.baggage.CorrelationScopeDecorator; +import brave.context.slf4j.MDCScopeDecorator; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link BravePropagationConfigurations}. + */ +class BravePropagationConfigurationsTests { + + /** + * Validates the assumption that {@link MDCScopeDecorator#newBuilder()} only + * configures traceId and spanId by default. The + * {@link BravePropagationConfigurations.PropagationWithBaggage#mdcCorrelationScopeDecoratorBuilder} + * method clears the builder's defaults and re-adds only these two fields so their MDC + * key names can be customized. If Brave adds new default fields in the future, the + * {@code .clear()} call in that method would silently drop them, and this test will + * catch that. + */ + @Test + void mdcScopeDecoratorBuilderShouldOnlyHaveTraceIdAndSpanIdByDefault() { + CorrelationScopeDecorator.Builder builder = MDCScopeDecorator.newBuilder(); + assertThat(builder.configs()).extracting((config) -> ((SingleCorrelationField) config).name()) + .containsExactlyInAnyOrder(BaggageFields.TRACE_ID.name(), BaggageFields.SPAN_ID.name()); + } + +} diff --git a/module/spring-boot-micrometer-tracing-opentelemetry/src/main/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/OpenTelemetryTracingAutoConfiguration.java b/module/spring-boot-micrometer-tracing-opentelemetry/src/main/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/OpenTelemetryTracingAutoConfiguration.java index c2bd6e6ed3d2..fec4ac315cf8 100644 --- a/module/spring-boot-micrometer-tracing-opentelemetry/src/main/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/OpenTelemetryTracingAutoConfiguration.java +++ b/module/spring-boot-micrometer-tracing-opentelemetry/src/main/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/OpenTelemetryTracingAutoConfiguration.java @@ -59,6 +59,7 @@ import org.springframework.boot.micrometer.tracing.autoconfigure.MicrometerTracingAutoConfiguration; import org.springframework.boot.micrometer.tracing.autoconfigure.NoopTracerAutoConfiguration; import org.springframework.boot.micrometer.tracing.autoconfigure.TracingProperties; +import org.springframework.boot.micrometer.tracing.autoconfigure.TracingProperties.Mdc; import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.OpenTelemetryPropagationConfigurations.NoPropagation; import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.OpenTelemetryPropagationConfigurations.PropagationWithBaggage; import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.OpenTelemetryPropagationConfigurations.PropagationWithoutBaggage; @@ -219,7 +220,8 @@ OtelCurrentTraceContext otelCurrentTraceContext() { @Bean @ConditionalOnMissingBean Slf4JEventListener otelSlf4JEventListener() { - return new Slf4JEventListener(); + Mdc mdc = this.tracingProperties.getMdc(); + return new Slf4JEventListener(mdc.getTraceIdKey(), mdc.getSpanIdKey()); } @Bean diff --git a/module/spring-boot-micrometer-tracing-opentelemetry/src/test/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/OpenTelemetryTracingAutoConfigurationTests.java b/module/spring-boot-micrometer-tracing-opentelemetry/src/test/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/OpenTelemetryTracingAutoConfigurationTests.java index 50f47d4286a6..6add85899280 100644 --- a/module/spring-boot-micrometer-tracing-opentelemetry/src/test/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/OpenTelemetryTracingAutoConfigurationTests.java +++ b/module/spring-boot-micrometer-tracing-opentelemetry/src/test/java/org/springframework/boot/micrometer/tracing/opentelemetry/autoconfigure/OpenTelemetryTracingAutoConfigurationTests.java @@ -190,6 +190,27 @@ void samplerCanBeSetToParentBasedTraceIdRatio() { }); } + @Test + void slf4jEventListenerUsesDefaultMdcKeys() { + this.contextRunner.run((context) -> { + Slf4JEventListener listener = context.getBean(Slf4JEventListener.class); + assertThat(listener).hasFieldOrPropertyWithValue("traceIdKey", "traceId") + .hasFieldOrPropertyWithValue("spanIdKey", "spanId"); + }); + } + + @Test + void slf4jEventListenerUsesCustomMdcKeys() { + this.contextRunner + .withPropertyValues("management.tracing.mdc.trace-id-key=customTraceId", + "management.tracing.mdc.span-id-key=customSpanId") + .run((context) -> { + Slf4JEventListener listener = context.getBean(Slf4JEventListener.class); + assertThat(listener).hasFieldOrPropertyWithValue("traceIdKey", "customTraceId") + .hasFieldOrPropertyWithValue("spanIdKey", "customSpanId"); + }); + } + @ParameterizedTest @ValueSource(strings = { "io.micrometer.tracing.otel", "io.opentelemetry.sdk", "io.opentelemetry.api" }) void shouldNotSupplyBeansIfDependencyIsMissing(String packageName) { diff --git a/module/spring-boot-micrometer-tracing/src/main/java/org/springframework/boot/micrometer/tracing/autoconfigure/TracingProperties.java b/module/spring-boot-micrometer-tracing/src/main/java/org/springframework/boot/micrometer/tracing/autoconfigure/TracingProperties.java index b1588f9f054e..02f70a7c64fa 100644 --- a/module/spring-boot-micrometer-tracing/src/main/java/org/springframework/boot/micrometer/tracing/autoconfigure/TracingProperties.java +++ b/module/spring-boot-micrometer-tracing/src/main/java/org/springframework/boot/micrometer/tracing/autoconfigure/TracingProperties.java @@ -53,6 +53,11 @@ public class TracingProperties { */ private final Exemplars exemplars = new Exemplars(); + /** + * {@code org.slf4j.MDC} key configuration for trace and span IDs. + */ + private final Mdc mdc = new Mdc(); + public Sampling getSampling() { return this.sampling; } @@ -69,6 +74,10 @@ public Exemplars getExemplars() { return this.exemplars; } + public Mdc getMdc() { + return this.mdc; + } + public static class Sampling { /** @@ -258,6 +267,39 @@ public enum PropagationType { } + /** + * {@code org.slf4j.MDC} key configuration for trace and span IDs. + */ + public static class Mdc { + + /** + * Key under which the trace ID is added to the {@code org.slf4j.MDC}. + */ + private String traceIdKey = "traceId"; + + /** + * Key under which the span ID is added to the {@code org.slf4j.MDC}. + */ + private String spanIdKey = "spanId"; + + public String getTraceIdKey() { + return this.traceIdKey; + } + + public void setTraceIdKey(String traceIdKey) { + this.traceIdKey = traceIdKey; + } + + public String getSpanIdKey() { + return this.spanIdKey; + } + + public void setSpanIdKey(String spanIdKey) { + this.spanIdKey = spanIdKey; + } + + } + /** * Exemplars configuration. */