Fixed custom propagation mode option
with this change when CUSTOM mode is turned on we will search for user provided Propagation bean or else noop fixes gh-1836
This commit is contained in:
@@ -30,6 +30,7 @@ import brave.propagation.TraceContextOrSamplingFlags;
|
|||||||
import brave.propagation.aws.AWSPropagation;
|
import brave.propagation.aws.AWSPropagation;
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.cloud.sleuth.brave.propagation.PropagationFactorySupplier;
|
import org.springframework.cloud.sleuth.brave.propagation.PropagationFactorySupplier;
|
||||||
import org.springframework.cloud.sleuth.brave.propagation.PropagationType;
|
import org.springframework.cloud.sleuth.brave.propagation.PropagationType;
|
||||||
|
|
||||||
@@ -56,7 +57,7 @@ public class CompositePropagationFactorySupplier implements PropagationFactorySu
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Propagation.Factory get() {
|
public Propagation.Factory get() {
|
||||||
return new CompositePropagationFactory(
|
return new CompositePropagationFactory(this.beanFactory,
|
||||||
this.beanFactory.getBeanProvider(BraveBaggageManager.class).getIfAvailable(BraveBaggageManager::new),
|
this.beanFactory.getBeanProvider(BraveBaggageManager.class).getIfAvailable(BraveBaggageManager::new),
|
||||||
this.localFields, this.types);
|
this.localFields, this.types);
|
||||||
}
|
}
|
||||||
@@ -69,8 +70,8 @@ class CompositePropagationFactory extends Propagation.Factory implements Propaga
|
|||||||
|
|
||||||
private final List<PropagationType> types;
|
private final List<PropagationType> types;
|
||||||
|
|
||||||
CompositePropagationFactory(BraveBaggageManager braveBaggageManager, List<String> localFields,
|
CompositePropagationFactory(BeanFactory beanFactory, BraveBaggageManager braveBaggageManager,
|
||||||
List<PropagationType> types) {
|
List<String> localFields, List<PropagationType> types) {
|
||||||
this.types = types;
|
this.types = types;
|
||||||
this.mapping.put(PropagationType.AWS, AWSPropagation.FACTORY.get());
|
this.mapping.put(PropagationType.AWS, AWSPropagation.FACTORY.get());
|
||||||
// Note: Versions <2.2.3 use injectFormat(MULTI) for non-remote (ex
|
// Note: Versions <2.2.3 use injectFormat(MULTI) for non-remote (ex
|
||||||
@@ -79,7 +80,7 @@ class CompositePropagationFactory extends Propagation.Factory implements Propaga
|
|||||||
this.mapping.put(PropagationType.B3,
|
this.mapping.put(PropagationType.B3,
|
||||||
B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.SINGLE_NO_PARENT).build().get());
|
B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.SINGLE_NO_PARENT).build().get());
|
||||||
this.mapping.put(PropagationType.W3C, new W3CPropagation(braveBaggageManager, localFields));
|
this.mapping.put(PropagationType.W3C, new W3CPropagation(braveBaggageManager, localFields));
|
||||||
this.mapping.put(PropagationType.CUSTOM, NoOpPropagation.INSTANCE);
|
this.mapping.put(PropagationType.CUSTOM, new LazyPropagation(beanFactory.getBeanProvider(Propagation.class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -116,6 +117,32 @@ class CompositePropagationFactory extends Propagation.Factory implements Propaga
|
|||||||
return StringPropagationAdapter.create(this, keyFactory);
|
return StringPropagationAdapter.create(this, keyFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static final class LazyPropagation implements Propagation<String> {
|
||||||
|
|
||||||
|
private final ObjectProvider<Propagation> delegate;
|
||||||
|
|
||||||
|
private LazyPropagation(ObjectProvider<Propagation> delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> keys() {
|
||||||
|
return this.delegate.getIfAvailable(() -> NoOpPropagation.INSTANCE).keys();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R> TraceContext.Injector<R> injector(Setter<R, String> setter) {
|
||||||
|
return this.delegate.getIfAvailable(() -> NoOpPropagation.INSTANCE).injector(setter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R> TraceContext.Extractor<R> extractor(Getter<R, String> getter) {
|
||||||
|
return this.delegate.getIfAvailable(() -> NoOpPropagation.INSTANCE).extractor(getter);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static class NoOpPropagation implements Propagation<String> {
|
private static class NoOpPropagation implements Propagation<String> {
|
||||||
|
|
||||||
static final NoOpPropagation INSTANCE = new NoOpPropagation();
|
static final NoOpPropagation INSTANCE = new NoOpPropagation();
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2021 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.bridge;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import brave.internal.codec.HexCodec;
|
||||||
|
import brave.internal.propagation.StringPropagationAdapter;
|
||||||
|
import brave.propagation.Propagation;
|
||||||
|
import brave.propagation.TraceContext;
|
||||||
|
import brave.propagation.TraceContextOrSamplingFlags;
|
||||||
|
import org.assertj.core.api.BDDAssertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
|
import org.springframework.cloud.loadbalancer.support.SimpleObjectProvider;
|
||||||
|
import org.springframework.cloud.sleuth.brave.propagation.PropagationType;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
class CompositePropagationFactorySupplierTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void should_pick_custom_registered_propagation_when_custom_mode_picked() {
|
||||||
|
BeanFactory beanFactory = Mockito.mock(BeanFactory.class);
|
||||||
|
Mockito.when(beanFactory.getBeanProvider(BraveBaggageManager.class))
|
||||||
|
.thenReturn(new SimpleObjectProvider(new BraveBaggageManager()));
|
||||||
|
Mockito.when(beanFactory.getBeanProvider(Propagation.class))
|
||||||
|
.thenReturn(new SimpleObjectProvider(new CustomTracePropagation()));
|
||||||
|
|
||||||
|
CompositePropagationFactorySupplier supplier = new CompositePropagationFactorySupplier(beanFactory,
|
||||||
|
Collections.emptyList(), Collections.singletonList(PropagationType.CUSTOM));
|
||||||
|
|
||||||
|
BDDAssertions.then(supplier.get().get().keys()).containsExactly(CustomTraceExtractor.CUSTOM_TRACE_HEADER);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomTracePropagation extends Propagation.Factory implements Propagation<String> {
|
||||||
|
|
||||||
|
public static final List<String> KEYS = Collections.singletonList(CustomTraceExtractor.CUSTOM_TRACE_HEADER);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> keys() {
|
||||||
|
return KEYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R> TraceContext.Injector<R> injector(Setter<R, String> setter) {
|
||||||
|
return (traceContext, request) -> {
|
||||||
|
String trace = traceContext.traceIdString() + ":" + traceContext.spanIdString();
|
||||||
|
setter.put(request, CustomTraceExtractor.CUSTOM_TRACE_HEADER, trace);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R> TraceContext.Extractor<R> extractor(Getter<R, String> getter) {
|
||||||
|
Objects.requireNonNull(getter);
|
||||||
|
return new CustomTraceExtractor<>(getter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <K> Propagation<K> create(KeyFactory<K> keyFactory) {
|
||||||
|
return StringPropagationAdapter.create(this, keyFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomTraceExtractor<R> implements TraceContext.Extractor<R> {
|
||||||
|
|
||||||
|
static final String CUSTOM_TRACE_HEADER = "x-custom-trace";
|
||||||
|
|
||||||
|
final Propagation.Getter<R, String> getter;
|
||||||
|
|
||||||
|
CustomTraceExtractor(Propagation.Getter<R, String> getter) {
|
||||||
|
this.getter = getter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("ReturnCount")
|
||||||
|
public TraceContextOrSamplingFlags extract(R request) {
|
||||||
|
String traceString = getter.get(request, CUSTOM_TRACE_HEADER);
|
||||||
|
if (!StringUtils.hasText(traceString)) {
|
||||||
|
return TraceContextOrSamplingFlags.EMPTY;
|
||||||
|
}
|
||||||
|
String[] trace = traceString.split(":");
|
||||||
|
if (trace.length != 2) {
|
||||||
|
return TraceContextOrSamplingFlags.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
TraceContext traceContext = TraceContext.newBuilder().traceId(HexCodec.lowerHexToUnsignedLong(trace[0]))
|
||||||
|
.spanId(HexCodec.lowerHexToUnsignedLong(trace[1])).build();
|
||||||
|
|
||||||
|
return TraceContextOrSamplingFlags.create(traceContext);
|
||||||
|
}
|
||||||
|
catch (NumberFormatException ex) {
|
||||||
|
return TraceContextOrSamplingFlags.EMPTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -80,4 +80,3 @@ public class TraceWebClientBeanPostProcessor implements BeanPostProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
|
|||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link BeanPostProcessor} that ensures that each {@link Feign.Builder} has
|
* {@link BeanPostProcessor} that ensures that each {@link Feign.Builder} has a trace
|
||||||
* a trace representation of a {@link Client}.
|
* representation of a {@link Client}.
|
||||||
*
|
*
|
||||||
* @author Marcin Grzejszczak
|
* @author Marcin Grzejszczak
|
||||||
* @since 3.0.2
|
* @since 3.0.2
|
||||||
|
|||||||
Reference in New Issue
Block a user