Only propgate b3 baggage when b3 picked; fixes gh-1781
This commit is contained in:
@@ -91,7 +91,7 @@ public class BraveAutoConfiguration {
|
||||
CurrentTraceContext currentTraceContext, Sampler sampler, SleuthProperties sleuthProperties,
|
||||
@Nullable List<SpanHandler> spanHandlers, @Nullable List<TracingCustomizer> tracingCustomizers) {
|
||||
Tracing.Builder builder = Tracing.newBuilder().sampler(sampler)
|
||||
.localServiceName(StringUtils.isEmpty(serviceName) ? DEFAULT_SERVICE_NAME : serviceName)
|
||||
.localServiceName(!StringUtils.hasText(serviceName) ? DEFAULT_SERVICE_NAME : serviceName)
|
||||
.propagationFactory(factory).currentTraceContext(currentTraceContext)
|
||||
.traceId128Bit(sleuthProperties.isTraceId128()).supportsJoin(sleuthProperties.isSupportsJoin());
|
||||
if (spanHandlers != null) {
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.sleuth.autoconfig.SleuthBaggageProperties;
|
||||
import org.springframework.cloud.sleuth.brave.propagation.PropagationFactorySupplier;
|
||||
import org.springframework.cloud.sleuth.brave.propagation.PropagationType;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -125,9 +126,10 @@ class BraveBaggageConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
Propagation.Factory sleuthPropagation(BaggagePropagation.FactoryBuilder factoryBuilder,
|
||||
Propagation.Factory sleuthPropagationWithB3Baggage(BaggagePropagation.FactoryBuilder factoryBuilder,
|
||||
@Qualifier(BAGGAGE_KEYS) List<String> baggageKeys, @Qualifier(LOCAL_KEYS) List<String> localKeys,
|
||||
@Qualifier(PROPAGATION_KEYS) List<String> propagationKeys, SleuthBaggageProperties sleuthBaggageProperties,
|
||||
SleuthPropagationProperties sleuthPropagationProperties, PropagationFactorySupplier supplier,
|
||||
@Nullable List<BaggagePropagationCustomizer> baggagePropagationCustomizers) {
|
||||
|
||||
Set<String> localFields = redirectOldPropertyToNew(LOCAL_KEYS, localKeys, "spring.sleuth.baggage.local-fields",
|
||||
@@ -159,7 +161,13 @@ class BraveBaggageConfiguration {
|
||||
customizer.customize(factoryBuilder);
|
||||
}
|
||||
}
|
||||
return factoryBuilder.build();
|
||||
Propagation.Factory delegate = factoryBuilder.build();
|
||||
Propagation.Factory factoryFromSupplier = supplier.get();
|
||||
final boolean hasB3 = sleuthPropagationProperties.getType().contains(PropagationType.B3);
|
||||
if (hasB3) {
|
||||
return delegate;
|
||||
}
|
||||
return new BaggageFactoryWrapper(delegate, factoryFromSupplier);
|
||||
}
|
||||
|
||||
static Set<String> redirectOldPropertyToNew(String oldProperty, List<String> oldValue, String newProperty,
|
||||
@@ -290,4 +298,65 @@ class BraveBaggageConfiguration {
|
||||
|
||||
}
|
||||
|
||||
static class BaggageFactoryWrapper extends Propagation.Factory {
|
||||
|
||||
private final Propagation.Factory delegate;
|
||||
|
||||
private final Propagation.Factory factoryFromSupplier;
|
||||
|
||||
BaggageFactoryWrapper(Propagation.Factory delegate, Propagation.Factory factoryFromSupplier) {
|
||||
this.delegate = delegate;
|
||||
this.factoryFromSupplier = factoryFromSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsJoin() {
|
||||
return delegate.supportsJoin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requires128BitTraceId() {
|
||||
return delegate.requires128BitTraceId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Propagation<String> get() {
|
||||
Propagation<String> propagation = delegate.get();
|
||||
return delegateWithoutB3Baggage(factoryFromSupplier, propagation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TraceContext decorate(TraceContext context) {
|
||||
return delegate.decorate(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K> Propagation<K> create(Propagation.KeyFactory<K> keyFactory) {
|
||||
Propagation<K> propagation = delegate.create(keyFactory);
|
||||
return delegateWithoutB3Baggage(factoryFromSupplier, propagation);
|
||||
}
|
||||
|
||||
private <K> Propagation<K> delegateWithoutB3Baggage(Propagation.Factory factoryFromSupplier,
|
||||
Propagation<K> propagation) {
|
||||
return new Propagation<K>() {
|
||||
@Override
|
||||
public List<K> keys() {
|
||||
return propagation.keys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> TraceContext.Injector<R> injector(Setter<R, K> setter) {
|
||||
// We don't want to inject baggage in the Brave way
|
||||
return factoryFromSupplier.get().injector((Setter<R, String>) setter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> TraceContext.Extractor<R> extractor(Getter<R, K> getter) {
|
||||
return propagation.extractor(getter);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -33,8 +33,13 @@ import org.springframework.cloud.sleuth.BaggageManager;
|
||||
import org.springframework.cloud.sleuth.autoconfig.SleuthBaggageProperties;
|
||||
import org.springframework.cloud.sleuth.otel.propagation.BaggageTextMapPropagator;
|
||||
import org.springframework.cloud.sleuth.otel.propagation.CompositeTextMapPropagator;
|
||||
import org.springframework.cloud.sleuth.otel.propagation.PropagationType;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
@@ -74,7 +79,7 @@ class OtelPropagationConfiguration {
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(name = "spring.sleuth.otel.propagation.sleuth-baggage.enabled", matchIfMissing = true)
|
||||
@Conditional(B3PresentOrPropertyEnabledCondition.class)
|
||||
static class BaggagePropagatorConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -84,4 +89,16 @@ class OtelPropagationConfiguration {
|
||||
|
||||
}
|
||||
|
||||
static class B3PresentOrPropertyEnabledCondition implements Condition {
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
String type = context.getEnvironment().getProperty("spring.sleuth.propagation.type", "").toLowerCase();
|
||||
boolean sleuthBaggageEnabled = context.getEnvironment()
|
||||
.getProperty("spring.sleuth.otel.propagation.sleuth-baggage.enabled", Boolean.class, false);
|
||||
return type.contains(PropagationType.B3.toString().toLowerCase()) || sleuthBaggageEnabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -84,6 +84,16 @@
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>mockwebserver</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<!-- Kotlin... -->
|
||||
<version>4.8.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2013-2020 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.cloud.sleuth.brave.baggage;
|
||||
|
||||
import brave.sampler.Sampler;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
|
||||
import org.springframework.cloud.sleuth.test.TestSpanHandler;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* @author Taras Danylchuk
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@ContextConfiguration(classes = W3CBaggageTests.Config.class)
|
||||
public class W3CBaggageTests extends org.springframework.cloud.sleuth.baggage.W3CBaggageTests {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
TestSpanHandler testSpanHandlerSupplier(brave.test.TestSpanHandler testSpanHandler) {
|
||||
return new BraveTestSpanHandler(testSpanHandler);
|
||||
}
|
||||
|
||||
@Bean
|
||||
Sampler alwaysSampler() {
|
||||
return Sampler.ALWAYS_SAMPLE;
|
||||
}
|
||||
|
||||
@Bean
|
||||
brave.test.TestSpanHandler braveTestSpanHandler() {
|
||||
return new brave.test.TestSpanHandler();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2013-2020 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.cloud.sleuth.baggage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
import org.assertj.core.api.BDDAssertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.cloud.sleuth.BaggageInScope;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @author Taras Danylchuk
|
||||
*/
|
||||
@ContextConfiguration(classes = W3CBaggageTests.TestConfig.class)
|
||||
@TestPropertySource(properties = { "spring.sleuth.baggage.remote-fields[0]=foo", "spring.sleuth.propagation.type=W3C" })
|
||||
public abstract class W3CBaggageTests {
|
||||
|
||||
@Autowired
|
||||
Tracer tracer;
|
||||
|
||||
@Autowired
|
||||
RestTemplate restTemplate;
|
||||
|
||||
@Autowired
|
||||
MockWebServer mockWebServer;
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void shouldProduceOnlyW3cBaggageEntries() throws InterruptedException {
|
||||
this.mockWebServer.enqueue(new MockResponse().setBody("hello"));
|
||||
Span span = this.tracer.nextSpan();
|
||||
|
||||
try (Tracer.SpanInScope spanInScope = this.tracer.withSpan(span.start())) {
|
||||
try (BaggageInScope bs = this.tracer.createBaggage("foo").set("bar")) {
|
||||
// when
|
||||
this.restTemplate.getForObject(this.mockWebServer.url("/baggage").toString(), String.class);
|
||||
|
||||
// then
|
||||
RecordedRequest request = this.mockWebServer.takeRequest(1, TimeUnit.SECONDS);
|
||||
Map<String, List<String>> map = request.getHeaders().toMultimap();
|
||||
BDDAssertions.then(map).doesNotContainKey("foo");
|
||||
List<String> baggage = map.get("baggage");
|
||||
BDDAssertions.then(baggage.stream().anyMatch(s -> s.contains("foo=bar"))).isTrue();
|
||||
}
|
||||
finally {
|
||||
span.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class TestConfig {
|
||||
|
||||
@Bean
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
@Bean
|
||||
MockWebServer mockWebServer() throws IOException {
|
||||
MockWebServer mockWebServer = new MockWebServer();
|
||||
mockWebServer.start();
|
||||
return mockWebServer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -90,6 +90,16 @@
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>mockwebserver</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<!-- Kotlin... -->
|
||||
<version>4.8.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
@@ -42,6 +43,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
|
||||
|
||||
@SpringBootTest(webEnvironment = RANDOM_PORT)
|
||||
@ContextConfiguration(classes = MultipleHopsIntegrationTests.Config.class)
|
||||
@TestPropertySource(properties = "spring.sleuth.otel.propagation.sleuth-baggage.enabled=true")
|
||||
public class MultipleHopsIntegrationTests
|
||||
extends org.springframework.cloud.sleuth.baggage.multiple.MultipleHopsIntegrationTests {
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2013-2020 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.cloud.sleuth.otel.bridge;
|
||||
|
||||
import io.opentelemetry.sdk.trace.samplers.Sampler;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.sleuth.otel.OtelTestSpanHandler;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* @author Taras Danylchuk
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@ContextConfiguration(classes = W3CBaggageTests.Config.class)
|
||||
public class W3CBaggageTests extends org.springframework.cloud.sleuth.baggage.W3CBaggageTests {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
OtelTestSpanHandler testSpanHandlerSupplier() {
|
||||
return new OtelTestSpanHandler(new ArrayListSpanProcessor());
|
||||
}
|
||||
|
||||
@Bean
|
||||
Sampler alwaysSampler() {
|
||||
return Sampler.alwaysOn();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user