Merge pull request #37435 from adispezo

* pr/37435:
  Adapt to changes in Brave tagged fields handling
  Add local and tagged correlation fields

Closes gh-37435
This commit is contained in:
Moritz Halbritter 2024-01-09 11:50:56 +01:00
commit 2551735093
8 changed files with 109 additions and 27 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@ -70,13 +70,17 @@ import org.springframework.core.env.Environment;
BravePropagationConfigurations.NoPropagation.class })
public class BraveAutoConfiguration {
static final BraveBaggageManager BRAVE_BAGGAGE_MANAGER = new BraveBaggageManager();
/**
* Default value for application name if {@code spring.application.name} is not set.
*/
private static final String DEFAULT_APPLICATION_NAME = "application";
private final TracingProperties tracingProperties;
BraveAutoConfiguration(TracingProperties tracingProperties) {
this.tracingProperties = tracingProperties;
}
@Bean
@ConditionalOnMissingBean
@Order(Ordered.HIGHEST_PRECEDENCE)
@ -88,22 +92,22 @@ public class BraveAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public Tracing braveTracing(Environment environment, TracingProperties properties, List<SpanHandler> spanHandlers,
Tracing braveTracing(Environment environment, List<SpanHandler> spanHandlers,
List<TracingCustomizer> tracingCustomizers, CurrentTraceContext currentTraceContext,
Factory propagationFactory, Sampler sampler) {
if (properties.getBrave().isSpanJoiningSupported()) {
if (properties.getPropagation().getType() != null
&& properties.getPropagation().getType().contains(PropagationType.W3C)) {
if (this.tracingProperties.getBrave().isSpanJoiningSupported()) {
if (this.tracingProperties.getPropagation().getType() != null
&& this.tracingProperties.getPropagation().getType().contains(PropagationType.W3C)) {
throw new IncompatibleConfigurationException("management.tracing.propagation.type",
"management.tracing.brave.span-joining-supported");
}
if (properties.getPropagation().getType() == null
&& properties.getPropagation().getProduce().contains(PropagationType.W3C)) {
if (this.tracingProperties.getPropagation().getType() == null
&& this.tracingProperties.getPropagation().getProduce().contains(PropagationType.W3C)) {
throw new IncompatibleConfigurationException("management.tracing.propagation.produce",
"management.tracing.brave.span-joining-supported");
}
if (properties.getPropagation().getType() == null
&& properties.getPropagation().getConsume().contains(PropagationType.W3C)) {
if (this.tracingProperties.getPropagation().getType() == null
&& this.tracingProperties.getPropagation().getConsume().contains(PropagationType.W3C)) {
throw new IncompatibleConfigurationException("management.tracing.propagation.consume",
"management.tracing.brave.span-joining-supported");
}
@ -112,7 +116,7 @@ public class BraveAutoConfiguration {
Builder builder = Tracing.newBuilder()
.currentTraceContext(currentTraceContext)
.traceId128Bit(true)
.supportsJoin(properties.getBrave().isSpanJoiningSupported())
.supportsJoin(this.tracingProperties.getBrave().isSpanJoiningSupported())
.propagationFactory(propagationFactory)
.sampler(sampler)
.localServiceName(applicationName);
@ -125,13 +129,13 @@ public class BraveAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public brave.Tracer braveTracer(Tracing tracing) {
brave.Tracer braveTracer(Tracing tracing) {
return tracing.tracer();
}
@Bean
@ConditionalOnMissingBean
public CurrentTraceContext braveCurrentTraceContext(List<CurrentTraceContext.ScopeDecorator> scopeDecorators,
CurrentTraceContext braveCurrentTraceContext(List<CurrentTraceContext.ScopeDecorator> scopeDecorators,
List<CurrentTraceContextCustomizer> currentTraceContextCustomizers) {
ThreadLocalCurrentTraceContext.Builder builder = ThreadLocalCurrentTraceContext.newBuilder();
scopeDecorators.forEach(builder::addScopeDecorator);
@ -143,14 +147,15 @@ public class BraveAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public Sampler braveSampler(TracingProperties properties) {
return Sampler.create(properties.getSampling().getProbability());
Sampler braveSampler() {
return Sampler.create(this.tracingProperties.getSampling().getProbability());
}
@Bean
@ConditionalOnMissingBean(io.micrometer.tracing.Tracer.class)
BraveTracer braveTracerBridge(brave.Tracer tracer, CurrentTraceContext currentTraceContext) {
return new BraveTracer(tracer, new BraveCurrentTraceContext(currentTraceContext), BRAVE_BAGGAGE_MANAGER);
return new BraveTracer(tracer, new BraveCurrentTraceContext(currentTraceContext),
new BraveBaggageManager(this.tracingProperties.getBaggage().getTagFields()));
}
@Bean

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@ -31,6 +31,7 @@ import brave.propagation.CurrentTraceContext.ScopeDecorator;
import brave.propagation.Propagation;
import brave.propagation.Propagation.Factory;
import brave.propagation.Propagation.KeyFactory;
import io.micrometer.tracing.brave.bridge.BraveBaggageManager;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.autoconfigure.tracing.TracingProperties.Baggage.Correlation;
@ -90,7 +91,8 @@ class BravePropagationConfigurations {
baggagePropagationCustomizers.orderedStream()
.forEach((customizer) -> customizer.customize(throwAwayBuilder));
CompositePropagationFactory propagationFactory = CompositePropagationFactory.create(
this.tracingProperties.getPropagation(), BraveAutoConfiguration.BRAVE_BAGGAGE_MANAGER,
this.tracingProperties.getPropagation(),
new BraveBaggageManager(this.tracingProperties.getBaggage().getTagFields()),
LocalBaggageFields.extractFrom(throwAwayBuilder));
FactoryBuilder builder = BaggagePropagation.newFactoryBuilder(propagationFactory);
throwAwayBuilder.configs().forEach(builder::add);
@ -110,13 +112,16 @@ class BravePropagationConfigurations {
}
@Bean
@Order(0)
BaggagePropagationCustomizer remoteFieldsBaggagePropagationCustomizer() {
return (builder) -> {
List<String> remoteFields = this.tracingProperties.getBaggage().getRemoteFields();
for (String fieldName : remoteFields) {
builder.add(BaggagePropagationConfig.SingleBaggageField.remote(BaggageField.create(fieldName)));
}
List<String> localFields = this.tracingProperties.getBaggage().getLocalFields();
for (String localFieldName : localFields) {
builder.add(BaggagePropagationConfig.SingleBaggageField.local(BaggageField.create(localFieldName)));
}
};
}

View File

@ -16,7 +16,6 @@
package org.springframework.boot.actuate.autoconfigure.tracing;
import java.util.Collections;
import java.util.List;
import io.micrometer.tracing.SpanCustomizer;
@ -47,6 +46,8 @@ import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessorBuilder;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.SpringBootVersion;
@ -57,6 +58,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.util.CollectionUtils;
/**
* {@link EnableAutoConfiguration Auto-configuration} for OpenTelemetry tracing.
@ -75,10 +77,15 @@ import org.springframework.context.annotation.Import;
OpenTelemetryPropagationConfigurations.NoPropagation.class })
public class OpenTelemetryAutoConfiguration {
private static final Log logger = LogFactory.getLog(OpenTelemetryAutoConfiguration.class);
private final TracingProperties tracingProperties;
OpenTelemetryAutoConfiguration(TracingProperties tracingProperties) {
this.tracingProperties = tracingProperties;
if (!CollectionUtils.isEmpty(this.tracingProperties.getBaggage().getLocalFields())) {
logger.warn("Local fields are not supported when using OpenTelemetry!");
}
}
@Bean
@ -137,9 +144,10 @@ public class OpenTelemetryAutoConfiguration {
@ConditionalOnMissingBean(io.micrometer.tracing.Tracer.class)
OtelTracer micrometerOtelTracer(Tracer tracer, EventPublisher eventPublisher,
OtelCurrentTraceContext otelCurrentTraceContext) {
List<String> remoteFields = this.tracingProperties.getBaggage().getRemoteFields();
List<String> tagFields = this.tracingProperties.getBaggage().getTagFields();
return new OtelTracer(tracer, otelCurrentTraceContext, eventPublisher,
new OtelBaggageManager(otelCurrentTraceContext, this.tracingProperties.getBaggage().getRemoteFields(),
Collections.emptyList()));
new OtelBaggageManager(otelCurrentTraceContext, remoteFields, tagFields));
}
@Bean

View File

@ -16,7 +16,6 @@
package org.springframework.boot.actuate.autoconfigure.tracing;
import java.util.Collections;
import java.util.List;
import io.micrometer.tracing.otel.bridge.OtelBaggageManager;
@ -73,8 +72,9 @@ class OpenTelemetryPropagationConfigurations {
@ConditionalOnEnabledTracing
TextMapPropagator textMapPropagatorWithBaggage(OtelCurrentTraceContext otelCurrentTraceContext) {
List<String> remoteFields = this.tracingProperties.getBaggage().getRemoteFields();
List<String> tagFields = this.tracingProperties.getBaggage().getTagFields();
BaggageTextMapPropagator baggagePropagator = new BaggageTextMapPropagator(remoteFields,
new OtelBaggageManager(otelCurrentTraceContext, remoteFields, Collections.emptyList()));
new OtelBaggageManager(otelCurrentTraceContext, remoteFields, tagFields));
return CompositeTextMapPropagator.create(this.tracingProperties.getPropagation(), baggagePropagator);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@ -103,6 +103,17 @@ public class TracingProperties {
*/
private List<String> remoteFields = new ArrayList<>();
/**
* List of fields that should be accessible within the JVM process but not
* propagated over the wire. Local fields are not supported with OpenTelemetry.
*/
private List<String> localFields = new ArrayList<>();
/**
* List of fields that should automatically become tags.
*/
private List<String> tagFields = new ArrayList<>();
public boolean isEnabled() {
return this.enabled;
}
@ -123,10 +134,26 @@ public class TracingProperties {
return this.remoteFields;
}
public List<String> getLocalFields() {
return this.localFields;
}
public List<String> getTagFields() {
return this.tagFields;
}
public void setRemoteFields(List<String> remoteFields) {
this.remoteFields = remoteFields;
}
public void setLocalFields(List<String> localFields) {
this.localFields = localFields;
}
public void setTagFields(List<String> tagFields) {
this.tagFields = tagFields;
}
public static class Correlation {
/**

View File

@ -227,6 +227,16 @@ class BaggagePropagationIntegrationTests {
"management.tracing.baggage.remote-fields=x-vcap-request-id,country-code,bp",
"management.tracing.baggage.correlation.fields=country-code,bp");
}
},
BRAVE_LOCAL_FIELDS {
@Override
public ApplicationContextRunner get() {
return new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(BraveAutoConfiguration.class))
.withPropertyValues("management.tracing.baggage.local-fields=country-code,bp",
"management.tracing.baggage.correlation.fields=country-code,bp");
}
}
}

View File

@ -354,6 +354,16 @@ class BraveAutoConfigurationTests {
});
}
@Test
void shouldConfigureTaggedFields() {
this.contextRunner.withPropertyValues("management.tracing.baggage.tag-fields=t1").run((context) -> {
BraveTracer braveTracer = context.getBean(BraveTracer.class);
assertThat(braveTracer).extracting("braveBaggageManager.tagFields")
.asInstanceOf(InstanceOfAssertFactories.list(String.class))
.containsExactly("t1");
});
}
private void injectToMap(Map<String, String> map, String key, String value) {
map.put(key, value);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@ -51,6 +51,7 @@ import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import io.opentelemetry.semconv.ResourceAttributes;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@ -272,6 +273,22 @@ class OpenTelemetryAutoConfigurationTests {
});
}
@Test
void shouldConfigureRemoteAndTaggedFields() {
this.contextRunner
.withPropertyValues("management.tracing.baggage.remote-fields=r1",
"management.tracing.baggage.tag-fields=t1")
.run((context) -> {
CompositeTextMapPropagator propagator = context.getBean(CompositeTextMapPropagator.class);
assertThat(propagator).extracting("baggagePropagator.baggageManager.remoteFields")
.asInstanceOf(InstanceOfAssertFactories.list(String.class))
.containsExactly("r1");
assertThat(propagator).extracting("baggagePropagator.baggageManager.tagFields")
.asInstanceOf(InstanceOfAssertFactories.list(String.class))
.containsExactly("t1");
});
}
@Test
void shouldCustomizeSdkTracerProvider() {
this.contextRunner.withUserConfiguration(SdkTracerProviderCustomizationConfiguration.class).run((context) -> {