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 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.PropagationType;
|
||||
|
||||
@@ -56,7 +57,7 @@ public class CompositePropagationFactorySupplier implements PropagationFactorySu
|
||||
|
||||
@Override
|
||||
public Propagation.Factory get() {
|
||||
return new CompositePropagationFactory(
|
||||
return new CompositePropagationFactory(this.beanFactory,
|
||||
this.beanFactory.getBeanProvider(BraveBaggageManager.class).getIfAvailable(BraveBaggageManager::new),
|
||||
this.localFields, this.types);
|
||||
}
|
||||
@@ -69,8 +70,8 @@ class CompositePropagationFactory extends Propagation.Factory implements Propaga
|
||||
|
||||
private final List<PropagationType> types;
|
||||
|
||||
CompositePropagationFactory(BraveBaggageManager braveBaggageManager, List<String> localFields,
|
||||
List<PropagationType> types) {
|
||||
CompositePropagationFactory(BeanFactory beanFactory, BraveBaggageManager braveBaggageManager,
|
||||
List<String> localFields, List<PropagationType> types) {
|
||||
this.types = types;
|
||||
this.mapping.put(PropagationType.AWS, AWSPropagation.FACTORY.get());
|
||||
// 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,
|
||||
B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.SINGLE_NO_PARENT).build().get());
|
||||
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
|
||||
@@ -116,6 +117,32 @@ class CompositePropagationFactory extends Propagation.Factory implements Propaga
|
||||
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> {
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* {@link BeanPostProcessor} that ensures that each {@link Feign.Builder} has
|
||||
* a trace representation of a {@link Client}.
|
||||
* {@link BeanPostProcessor} that ensures that each {@link Feign.Builder} has a trace
|
||||
* representation of a {@link Client}.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 3.0.2
|
||||
|
||||
Reference in New Issue
Block a user