Polish 'Add support for multiple tracing propagation formats'
See gh-35611
This commit is contained in:
parent
691b549e36
commit
9b72cc41ab
|
@ -167,8 +167,7 @@ public class BraveAutoConfiguration {
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
Factory propagationFactory(TracingProperties properties) {
|
Factory propagationFactory(TracingProperties properties) {
|
||||||
return CompositePropagationFactory.create(properties.getPropagation().getEffectiveProducedTypes(),
|
return CompositePropagationFactory.create(properties.getPropagation(), null);
|
||||||
properties.getPropagation().getEffectiveConsumedTypes());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -187,10 +186,9 @@ public class BraveAutoConfiguration {
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
BaggagePropagation.FactoryBuilder propagationFactoryBuilder(
|
BaggagePropagation.FactoryBuilder propagationFactoryBuilder(
|
||||||
ObjectProvider<BaggagePropagationCustomizer> baggagePropagationCustomizers) {
|
ObjectProvider<BaggagePropagationCustomizer> baggagePropagationCustomizers) {
|
||||||
Factory delegate = CompositePropagationFactory.create(BRAVE_BAGGAGE_MANAGER,
|
CompositePropagationFactory factory = CompositePropagationFactory
|
||||||
this.tracingProperties.getPropagation().getEffectiveProducedTypes(),
|
.create(this.tracingProperties.getPropagation(), BRAVE_BAGGAGE_MANAGER);
|
||||||
this.tracingProperties.getPropagation().getEffectiveConsumedTypes());
|
FactoryBuilder builder = BaggagePropagation.newFactoryBuilder(factory);
|
||||||
FactoryBuilder builder = BaggagePropagation.newFactoryBuilder(delegate);
|
|
||||||
baggagePropagationCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
|
baggagePropagationCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,56 +19,182 @@ package org.springframework.boot.actuate.autoconfigure.tracing;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import brave.internal.propagation.StringPropagationAdapter;
|
import brave.internal.propagation.StringPropagationAdapter;
|
||||||
import brave.propagation.B3Propagation;
|
import brave.propagation.B3Propagation;
|
||||||
import brave.propagation.Propagation;
|
import brave.propagation.Propagation;
|
||||||
|
import brave.propagation.Propagation.Factory;
|
||||||
import brave.propagation.TraceContext;
|
import brave.propagation.TraceContext;
|
||||||
import brave.propagation.TraceContextOrSamplingFlags;
|
import brave.propagation.TraceContextOrSamplingFlags;
|
||||||
|
import graphql.com.google.common.collect.Streams;
|
||||||
import io.micrometer.tracing.BaggageManager;
|
import io.micrometer.tracing.BaggageManager;
|
||||||
import io.micrometer.tracing.brave.bridge.W3CPropagation;
|
import io.micrometer.tracing.brave.bridge.W3CPropagation;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.tracing.TracingProperties.Propagation.PropagationType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Factory} which supports multiple tracing formats. It is able to configure
|
* {@link brave.propagation.Propagation.Factory Propagation factory} which supports
|
||||||
* different formats for injecting and for extracting.
|
* multiple tracing formats. It is able to configure different formats for injecting and
|
||||||
|
* for extracting.
|
||||||
*
|
*
|
||||||
* @author Marcin Grzejszczak
|
* @author Marcin Grzejszczak
|
||||||
* @author Moritz Halbritter
|
* @author Moritz Halbritter
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
class CompositePropagationFactory extends Propagation.Factory implements Propagation<String> {
|
class CompositePropagationFactory extends Propagation.Factory {
|
||||||
|
|
||||||
private final Collection<Propagation.Factory> injectorFactories;
|
private final PropagationFactories injectors;
|
||||||
|
|
||||||
private final Collection<Propagation.Factory> extractorFactories;
|
private final PropagationFactories extractors;
|
||||||
|
|
||||||
|
private final CompositePropagation propagation;
|
||||||
|
|
||||||
|
CompositePropagationFactory(Collection<Factory> injectorFactories, Collection<Factory> extractorFactories) {
|
||||||
|
this.injectors = new PropagationFactories(injectorFactories);
|
||||||
|
this.extractors = new PropagationFactories(extractorFactories);
|
||||||
|
this.propagation = new CompositePropagation(this.injectors, this.extractors);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<Factory> getInjectors() {
|
||||||
|
return this.injectors.stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsJoin() {
|
||||||
|
return this.injectors.supportsJoin() && this.extractors.supportsJoin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requires128BitTraceId() {
|
||||||
|
return this.injectors.requires128BitTraceId() || this.extractors.requires128BitTraceId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public <K> Propagation<K> create(Propagation.KeyFactory<K> keyFactory) {
|
||||||
|
return StringPropagationAdapter.create(this.propagation, keyFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TraceContext decorate(TraceContext context) {
|
||||||
|
return Streams.concat(this.injectors.stream(), this.extractors.stream())
|
||||||
|
.map((factory) -> factory.decorate(context))
|
||||||
|
.filter((decorated) -> decorated != context)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link CompositePropagationFactory}, which uses the given
|
||||||
|
* {@code injectionTypes} for injection and {@code extractionTypes} for extraction.
|
||||||
|
* @param properties the propagation properties
|
||||||
|
* @param baggageManager the baggage manager to use, or {@code null}
|
||||||
|
* @return the {@link CompositePropagationFactory}
|
||||||
|
*/
|
||||||
|
static CompositePropagationFactory create(TracingProperties.Propagation properties, BaggageManager baggageManager) {
|
||||||
|
PropagationFactoryMapper mapper = new PropagationFactoryMapper(baggageManager);
|
||||||
|
List<Factory> injectors = properties.getEffectiveProducedTypes().stream().map(mapper::map).toList();
|
||||||
|
List<Factory> extractors = properties.getEffectiveConsumedTypes().stream().map(mapper::map).toList();
|
||||||
|
return new CompositePropagationFactory(injectors, extractors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapper used to create a {@link brave.propagation.Propagation.Factory Propagation
|
||||||
|
* factory} from a {@link PropagationType}.
|
||||||
|
*/
|
||||||
|
private static class PropagationFactoryMapper {
|
||||||
|
|
||||||
|
private final BaggageManager baggageManager;
|
||||||
|
|
||||||
|
PropagationFactoryMapper(BaggageManager baggageManager) {
|
||||||
|
this.baggageManager = baggageManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
Propagation.Factory map(PropagationType type) {
|
||||||
|
return switch (type) {
|
||||||
|
case B3 -> b3Single();
|
||||||
|
case B3_MULTI -> b3Multi();
|
||||||
|
case W3C -> w3c();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new B3 propagation factory using a single B3 header.
|
||||||
|
* @return the B3 propagation factory
|
||||||
|
*/
|
||||||
|
private Propagation.Factory b3Single() {
|
||||||
|
return B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.SINGLE_NO_PARENT).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new B3 propagation factory using multiple B3 headers.
|
||||||
|
* @return the B3 propagation factory
|
||||||
|
*/
|
||||||
|
private Propagation.Factory b3Multi() {
|
||||||
|
return B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.MULTI).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new W3C propagation factory.
|
||||||
|
* @return the W3C propagation factory
|
||||||
|
*/
|
||||||
|
private Propagation.Factory w3c() {
|
||||||
|
return (this.baggageManager != null) ? new W3CPropagation(this.baggageManager, Collections.emptyList())
|
||||||
|
: new W3CPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A collection of propagation factories.
|
||||||
|
*/
|
||||||
|
private static class PropagationFactories {
|
||||||
|
|
||||||
|
private final List<Propagation.Factory> factories;
|
||||||
|
|
||||||
|
PropagationFactories(Collection<Factory> factories) {
|
||||||
|
this.factories = List.copyOf(factories);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean requires128BitTraceId() {
|
||||||
|
return stream().anyMatch(Propagation.Factory::requires128BitTraceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean supportsJoin() {
|
||||||
|
return stream().allMatch(Propagation.Factory::supportsJoin);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Propagation<String>> get() {
|
||||||
|
return stream().map(Factory::get).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<Factory> stream() {
|
||||||
|
return this.factories.stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A composite {@link Propagation}.
|
||||||
|
*/
|
||||||
|
private static class CompositePropagation implements Propagation<String> {
|
||||||
|
|
||||||
private final List<Propagation<String>> injectors;
|
private final List<Propagation<String>> injectors;
|
||||||
|
|
||||||
private final List<Propagation<String>> extractors;
|
private final List<Propagation<String>> extractors;
|
||||||
|
|
||||||
private final boolean supportsJoin;
|
|
||||||
|
|
||||||
private final boolean requires128BitTraceId;
|
|
||||||
|
|
||||||
private final List<String> keys;
|
private final List<String> keys;
|
||||||
|
|
||||||
CompositePropagationFactory(Collection<Factory> injectorFactories, Collection<Factory> extractorFactories) {
|
CompositePropagation(PropagationFactories injectorFactories, PropagationFactories extractorFactories) {
|
||||||
this.injectorFactories = injectorFactories;
|
this.injectors = injectorFactories.get();
|
||||||
this.extractorFactories = extractorFactories;
|
this.extractors = extractorFactories.get();
|
||||||
this.injectors = this.injectorFactories.stream().map(Factory::get).toList();
|
this.keys = Stream.concat(keys(this.injectors), keys(this.extractors)).distinct().toList();
|
||||||
this.extractors = this.extractorFactories.stream().map(Factory::get).toList();
|
|
||||||
this.supportsJoin = Stream.concat(this.injectorFactories.stream(), this.extractorFactories.stream())
|
|
||||||
.allMatch(Factory::supportsJoin);
|
|
||||||
this.requires128BitTraceId = Stream.concat(this.injectorFactories.stream(), this.extractorFactories.stream())
|
|
||||||
.anyMatch(Factory::requires128BitTraceId);
|
|
||||||
this.keys = Stream.concat(this.injectors.stream(), this.extractors.stream())
|
|
||||||
.flatMap((entry) -> entry.keys().stream())
|
|
||||||
.distinct()
|
|
||||||
.toList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<Factory> getInjectorFactories() {
|
private Stream<String> keys(List<Propagation<String>> propagations) {
|
||||||
return this.injectorFactories;
|
return propagations.stream().flatMap((propagation) -> propagation.keys().stream());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -78,124 +204,21 @@ class CompositePropagationFactory extends Propagation.Factory implements Propaga
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R> TraceContext.Injector<R> injector(Setter<R, String> setter) {
|
public <R> TraceContext.Injector<R> injector(Setter<R, String> setter) {
|
||||||
return (traceContext, request) -> {
|
return (traceContext, request) -> this.injectors.stream()
|
||||||
for (Propagation<String> injector : this.injectors) {
|
.map((propagation) -> propagation.injector(setter))
|
||||||
injector.injector(setter).inject(traceContext, request);
|
.forEach((injector) -> injector.inject(traceContext, request));
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R> TraceContext.Extractor<R> extractor(Getter<R, String> getter) {
|
public <R> TraceContext.Extractor<R> extractor(Getter<R, String> getter) {
|
||||||
return (request) -> {
|
return (request) -> this.extractors.stream()
|
||||||
for (Propagation<String> extractor : this.extractors) {
|
.map((propagation) -> propagation.extractor(getter))
|
||||||
TraceContextOrSamplingFlags extract = extractor.extractor(getter).extract(request);
|
.map((extractor) -> extractor.extract(request))
|
||||||
if (extract != TraceContextOrSamplingFlags.EMPTY) {
|
.filter(Predicate.not(TraceContextOrSamplingFlags.EMPTY::equals))
|
||||||
return extract;
|
.findFirst()
|
||||||
}
|
.orElse(TraceContextOrSamplingFlags.EMPTY);
|
||||||
}
|
|
||||||
return TraceContextOrSamplingFlags.EMPTY;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public <K> Propagation<K> create(KeyFactory<K> keyFactory) {
|
|
||||||
return StringPropagationAdapter.create(this, keyFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supportsJoin() {
|
|
||||||
return this.supportsJoin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean requires128BitTraceId() {
|
|
||||||
return this.requires128BitTraceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TraceContext decorate(TraceContext context) {
|
|
||||||
for (Factory injectorFactory : this.injectorFactories) {
|
|
||||||
TraceContext decorated = injectorFactory.decorate(context);
|
|
||||||
if (decorated != context) {
|
|
||||||
return decorated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Factory extractorFactory : this.extractorFactories) {
|
|
||||||
TraceContext decorated = extractorFactory.decorate(context);
|
|
||||||
if (decorated != context) {
|
|
||||||
return decorated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.decorate(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link CompositePropagationFactory}, which uses the given
|
|
||||||
* {@code injectionTypes} for injection and {@code extractionTypes} for extraction.
|
|
||||||
* @param baggageManager the baggage manager to use, or {@code null}
|
|
||||||
* @param injectionTypes the propagation types for injection
|
|
||||||
* @param extractionTypes the propagation types for extraction
|
|
||||||
* @return the {@link CompositePropagationFactory}
|
|
||||||
*/
|
|
||||||
static CompositePropagationFactory create(BaggageManager baggageManager,
|
|
||||||
Collection<TracingProperties.Propagation.PropagationType> injectionTypes,
|
|
||||||
Collection<TracingProperties.Propagation.PropagationType> extractionTypes) {
|
|
||||||
List<Factory> injectors = injectionTypes.stream()
|
|
||||||
.map((injection) -> factoryForType(baggageManager, injection))
|
|
||||||
.toList();
|
|
||||||
List<Factory> extractors = extractionTypes.stream()
|
|
||||||
.map((extraction) -> factoryForType(baggageManager, extraction))
|
|
||||||
.toList();
|
|
||||||
return new CompositePropagationFactory(injectors, extractors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link CompositePropagationFactory}, which uses the given
|
|
||||||
* {@code injectionTypes} for injection and {@code extractionTypes} for extraction.
|
|
||||||
* @param injectionTypes the propagation types for injection
|
|
||||||
* @param extractionTypes the propagation types for extraction
|
|
||||||
* @return the {@link CompositePropagationFactory}
|
|
||||||
*/
|
|
||||||
static CompositePropagationFactory create(Collection<TracingProperties.Propagation.PropagationType> injectionTypes,
|
|
||||||
Collection<TracingProperties.Propagation.PropagationType> extractionTypes) {
|
|
||||||
return create(null, injectionTypes, extractionTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Factory factoryForType(BaggageManager baggageManager,
|
|
||||||
TracingProperties.Propagation.PropagationType type) {
|
|
||||||
return switch (type) {
|
|
||||||
case B3 -> b3Single();
|
|
||||||
case B3_MULTI -> b3Multi();
|
|
||||||
case W3C -> w3c(baggageManager);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new B3 propagation factory using a single B3 header.
|
|
||||||
* @return the B3 propagation factory
|
|
||||||
*/
|
|
||||||
private static Factory b3Single() {
|
|
||||||
return B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.SINGLE_NO_PARENT).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new B3 propagation factory using multiple B3 headers.
|
|
||||||
* @return the B3 propagation factory
|
|
||||||
*/
|
|
||||||
private static Factory b3Multi() {
|
|
||||||
return B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.MULTI).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new W3C propagation factory.
|
|
||||||
* @param baggageManager baggage manager to use, or {@code null}
|
|
||||||
* @return the W3C propagation factory
|
|
||||||
*/
|
|
||||||
private static W3CPropagation w3c(BaggageManager baggageManager) {
|
|
||||||
return (baggageManager != null) ? new W3CPropagation(baggageManager, Collections.emptyList())
|
|
||||||
: new W3CPropagation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.springframework.boot.actuate.autoconfigure.tracing;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -32,6 +33,8 @@ import io.opentelemetry.context.propagation.TextMapPropagator;
|
||||||
import io.opentelemetry.context.propagation.TextMapSetter;
|
import io.opentelemetry.context.propagation.TextMapSetter;
|
||||||
import io.opentelemetry.extension.trace.propagation.B3Propagator;
|
import io.opentelemetry.extension.trace.propagation.B3Propagator;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.tracing.TracingProperties.Propagation.PropagationType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link TextMapPropagator} which supports multiple tracing formats. It is able to
|
* {@link TextMapPropagator} which supports multiple tracing formats. It is able to
|
||||||
* configure different formats for injecting and for extracting.
|
* configure different formats for injecting and for extracting.
|
||||||
|
@ -42,9 +45,9 @@ class CompositeTextMapPropagator implements TextMapPropagator {
|
||||||
|
|
||||||
private final Collection<TextMapPropagator> injectors;
|
private final Collection<TextMapPropagator> injectors;
|
||||||
|
|
||||||
private final Collection<TextMapPropagator> mutuallyExclusiveExtractors;
|
private final Collection<TextMapPropagator> extractors;
|
||||||
|
|
||||||
private final Collection<TextMapPropagator> alwaysRunningExtractors;
|
private final TextMapPropagator baggagePropagator;
|
||||||
|
|
||||||
private final Set<String> fields;
|
private final Set<String> fields;
|
||||||
|
|
||||||
|
@ -54,19 +57,24 @@ class CompositeTextMapPropagator implements TextMapPropagator {
|
||||||
* @param mutuallyExclusiveExtractors the mutually exclusive extractors. They are
|
* @param mutuallyExclusiveExtractors the mutually exclusive extractors. They are
|
||||||
* applied in order, and as soon as an extractor extracts a context, the other
|
* applied in order, and as soon as an extractor extracts a context, the other
|
||||||
* extractors after it are no longer invoked
|
* extractors after it are no longer invoked
|
||||||
* @param alwaysRunningExtractors the always running extractors. They always run in
|
* @param baggagePropagator the baggage propagator to use, or {@code null}
|
||||||
* order, regardless of the mutually exclusive extractors or whether the extractor
|
|
||||||
* before it has already extracted a context
|
|
||||||
*/
|
*/
|
||||||
CompositeTextMapPropagator(Collection<TextMapPropagator> injectors,
|
CompositeTextMapPropagator(Collection<TextMapPropagator> injectors,
|
||||||
Collection<TextMapPropagator> mutuallyExclusiveExtractors,
|
Collection<TextMapPropagator> mutuallyExclusiveExtractors, TextMapPropagator baggagePropagator) {
|
||||||
Collection<TextMapPropagator> alwaysRunningExtractors) {
|
|
||||||
this.injectors = injectors;
|
this.injectors = injectors;
|
||||||
this.mutuallyExclusiveExtractors = mutuallyExclusiveExtractors;
|
this.extractors = mutuallyExclusiveExtractors;
|
||||||
this.alwaysRunningExtractors = alwaysRunningExtractors;
|
this.baggagePropagator = baggagePropagator;
|
||||||
this.fields = concat(this.injectors, this.mutuallyExclusiveExtractors, this.alwaysRunningExtractors)
|
Set<String> fields = new LinkedHashSet<>();
|
||||||
.flatMap((entry) -> entry.fields().stream())
|
fields(this.injectors).forEach(fields::add);
|
||||||
.collect(Collectors.toSet());
|
fields(this.extractors).forEach(fields::add);
|
||||||
|
if (baggagePropagator != null) {
|
||||||
|
fields.addAll(baggagePropagator.fields());
|
||||||
|
}
|
||||||
|
this.fields = Collections.unmodifiableSet(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream<String> fields(Collection<TextMapPropagator> propagators) {
|
||||||
|
return propagators.stream().flatMap((propagator) -> propagator.fields().stream());
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<TextMapPropagator> getInjectors() {
|
Collection<TextMapPropagator> getInjectors() {
|
||||||
|
@ -80,11 +88,8 @@ class CompositeTextMapPropagator implements TextMapPropagator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C> void inject(Context context, C carrier, TextMapSetter<C> setter) {
|
public <C> void inject(Context context, C carrier, TextMapSetter<C> setter) {
|
||||||
if (context == null || setter == null) {
|
if (context != null && setter != null) {
|
||||||
return;
|
this.injectors.forEach((injector) -> injector.inject(context, carrier, setter));
|
||||||
}
|
|
||||||
for (TextMapPropagator injector : this.injectors) {
|
|
||||||
injector.inject(context, carrier, setter);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,70 +101,61 @@ class CompositeTextMapPropagator implements TextMapPropagator {
|
||||||
if (getter == null) {
|
if (getter == null) {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
Context currentContext = context;
|
Context result = this.extractors.stream()
|
||||||
for (TextMapPropagator extractor : this.mutuallyExclusiveExtractors) {
|
.map((extractor) -> extractor.extract(context, carrier, getter))
|
||||||
Context extractedContext = extractor.extract(currentContext, carrier, getter);
|
.filter((extracted) -> extracted != context)
|
||||||
if (extractedContext != currentContext) {
|
.findFirst()
|
||||||
currentContext = extractedContext;
|
.orElse(context);
|
||||||
break;
|
if (this.baggagePropagator != null) {
|
||||||
|
result = this.baggagePropagator.extract(result, carrier, getter);
|
||||||
}
|
}
|
||||||
}
|
return result;
|
||||||
for (TextMapPropagator extractor : this.alwaysRunningExtractors) {
|
|
||||||
currentContext = extractor.extract(currentContext, carrier, getter);
|
|
||||||
}
|
|
||||||
return currentContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link CompositeTextMapPropagator}, which uses the given
|
|
||||||
* {@code injectionTypes} for injection and {@code extractionTypes} for extraction.
|
|
||||||
* @param injectionTypes the propagation types for injection
|
|
||||||
* @param extractionTypes the propagation types for extraction
|
|
||||||
* @return the {@link CompositeTextMapPropagator}
|
|
||||||
*/
|
|
||||||
static TextMapPropagator create(Collection<TracingProperties.Propagation.PropagationType> injectionTypes,
|
|
||||||
Collection<TracingProperties.Propagation.PropagationType> extractionTypes) {
|
|
||||||
return create(null, injectionTypes, extractionTypes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link CompositeTextMapPropagator}, which uses the given
|
* Creates a new {@link CompositeTextMapPropagator}, which uses the given
|
||||||
* {@code injectionTypes} for injection and {@code extractionTypes} for extraction.
|
* {@code injectionTypes} for injection and {@code extractionTypes} for extraction.
|
||||||
|
* @param properties the tracing properties
|
||||||
* @param baggagePropagator the baggage propagator to use, or {@code null}
|
* @param baggagePropagator the baggage propagator to use, or {@code null}
|
||||||
* @param injectionTypes the propagation types for injection
|
|
||||||
* @param extractionTypes the propagation types for extraction
|
|
||||||
* @return the {@link CompositeTextMapPropagator}
|
* @return the {@link CompositeTextMapPropagator}
|
||||||
*/
|
*/
|
||||||
static CompositeTextMapPropagator create(TextMapPropagator baggagePropagator,
|
static TextMapPropagator create(TracingProperties.Propagation properties, TextMapPropagator baggagePropagator) {
|
||||||
Collection<TracingProperties.Propagation.PropagationType> injectionTypes,
|
TextMapPropagatorMapper mapper = new TextMapPropagatorMapper(baggagePropagator != null);
|
||||||
Collection<TracingProperties.Propagation.PropagationType> extractionTypes) {
|
List<TextMapPropagator> injectors = properties.getEffectiveProducedTypes()
|
||||||
List<TextMapPropagator> injectors = injectionTypes.stream()
|
.stream()
|
||||||
.map((injection) -> forType(injection, baggagePropagator != null))
|
.map(mapper::map)
|
||||||
.collect(Collectors.toCollection(ArrayList::new));
|
.collect(Collectors.toCollection(ArrayList::new));
|
||||||
if (baggagePropagator != null) {
|
if (baggagePropagator != null) {
|
||||||
injectors.add(baggagePropagator);
|
injectors.add(baggagePropagator);
|
||||||
}
|
}
|
||||||
List<TextMapPropagator> extractors = extractionTypes.stream()
|
List<TextMapPropagator> extractors = properties.getEffectiveProducedTypes().stream().map(mapper::map).toList();
|
||||||
.map((extraction) -> forType(extraction, baggagePropagator != null))
|
return new CompositeTextMapPropagator(injectors, extractors, baggagePropagator);
|
||||||
.toList();
|
|
||||||
return new CompositeTextMapPropagator(injectors, extractors,
|
|
||||||
(baggagePropagator != null) ? List.of(baggagePropagator) : Collections.emptyList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SafeVarargs
|
/**
|
||||||
private static <T> Stream<T> concat(Collection<T>... collections) {
|
* Mapper used to create a {@link TextMapPropagator} from a {@link PropagationType}.
|
||||||
Stream<T> result = Stream.empty();
|
*/
|
||||||
for (Collection<T> collection : collections) {
|
private static class TextMapPropagatorMapper {
|
||||||
result = Stream.concat(result, collection.stream());
|
|
||||||
|
private final boolean baggage;
|
||||||
|
|
||||||
|
TextMapPropagatorMapper(boolean baggage) {
|
||||||
|
this.baggage = baggage;
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
|
TextMapPropagator map(PropagationType type) {
|
||||||
|
return switch (type) {
|
||||||
|
case B3 -> b3Single();
|
||||||
|
case B3_MULTI -> b3Multi();
|
||||||
|
case W3C -> w3c();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new B3 propagator using a single B3 header.
|
* Creates a new B3 propagator using a single B3 header.
|
||||||
* @return the B3 propagator
|
* @return the B3 propagator
|
||||||
*/
|
*/
|
||||||
private static TextMapPropagator b3Single() {
|
private TextMapPropagator b3Single() {
|
||||||
return B3Propagator.injectingSingleHeader();
|
return B3Propagator.injectingSingleHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,28 +163,19 @@ class CompositeTextMapPropagator implements TextMapPropagator {
|
||||||
* Creates a new B3 propagator using multiple B3 headers.
|
* Creates a new B3 propagator using multiple B3 headers.
|
||||||
* @return the B3 propagator
|
* @return the B3 propagator
|
||||||
*/
|
*/
|
||||||
private static TextMapPropagator b3Multi() {
|
private TextMapPropagator b3Multi() {
|
||||||
return B3Propagator.injectingMultiHeaders();
|
return B3Propagator.injectingMultiHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new W3C propagator.
|
* Creates a new W3C propagator.
|
||||||
* @param baggage whether baggage propagation should be supported
|
|
||||||
* @return the W3C propagator
|
* @return the W3C propagator
|
||||||
*/
|
*/
|
||||||
private static TextMapPropagator w3c(boolean baggage) {
|
private TextMapPropagator w3c() {
|
||||||
if (!baggage) {
|
return (!this.baggage) ? W3CTraceContextPropagator.getInstance() : TextMapPropagator
|
||||||
return W3CTraceContextPropagator.getInstance();
|
.composite(W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance());
|
||||||
}
|
|
||||||
return TextMapPropagator.composite(W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TextMapPropagator forType(TracingProperties.Propagation.PropagationType type, boolean baggage) {
|
|
||||||
return switch (type) {
|
|
||||||
case B3 -> b3Single();
|
|
||||||
case B3_MULTI -> b3Multi();
|
|
||||||
case W3C -> w3c(baggage);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,9 +187,7 @@ public class OpenTelemetryAutoConfiguration {
|
||||||
List<String> remoteFields = this.tracingProperties.getBaggage().getRemoteFields();
|
List<String> remoteFields = this.tracingProperties.getBaggage().getRemoteFields();
|
||||||
BaggageTextMapPropagator baggagePropagator = new BaggageTextMapPropagator(remoteFields,
|
BaggageTextMapPropagator baggagePropagator = new BaggageTextMapPropagator(remoteFields,
|
||||||
new OtelBaggageManager(otelCurrentTraceContext, remoteFields, Collections.emptyList()));
|
new OtelBaggageManager(otelCurrentTraceContext, remoteFields, Collections.emptyList()));
|
||||||
return CompositeTextMapPropagator.create(baggagePropagator,
|
return CompositeTextMapPropagator.create(this.tracingProperties.getPropagation(), baggagePropagator);
|
||||||
this.tracingProperties.getPropagation().getEffectiveProducedTypes(),
|
|
||||||
this.tracingProperties.getPropagation().getEffectiveConsumedTypes());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -208,8 +206,7 @@ public class OpenTelemetryAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
TextMapPropagator textMapPropagator(TracingProperties properties) {
|
TextMapPropagator textMapPropagator(TracingProperties properties) {
|
||||||
return CompositeTextMapPropagator.create(properties.getPropagation().getEffectiveProducedTypes(),
|
return CompositeTextMapPropagator.create(properties.getPropagation(), null);
|
||||||
properties.getPropagation().getEffectiveConsumedTypes());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,10 +212,7 @@ public class TracingProperties {
|
||||||
* @return the effective context propagation types produced by the application
|
* @return the effective context propagation types produced by the application
|
||||||
*/
|
*/
|
||||||
List<PropagationType> getEffectiveProducedTypes() {
|
List<PropagationType> getEffectiveProducedTypes() {
|
||||||
if (this.type != null) {
|
return (this.type != null) ? this.type : this.produce;
|
||||||
return this.type;
|
|
||||||
}
|
|
||||||
return this.produce;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -224,10 +221,7 @@ public class TracingProperties {
|
||||||
* @return the effective context propagation types consumed by the application
|
* @return the effective context propagation types consumed by the application
|
||||||
*/
|
*/
|
||||||
List<PropagationType> getEffectiveConsumedTypes() {
|
List<PropagationType> getEffectiveConsumedTypes() {
|
||||||
if (this.type != null) {
|
return (this.type != null) ? this.type : this.consume;
|
||||||
return this.type;
|
|
||||||
}
|
|
||||||
return this.consume;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.springframework.boot.actuate.autoconfigure.tracing;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import brave.Span;
|
import brave.Span;
|
||||||
import brave.SpanCustomizer;
|
import brave.SpanCustomizer;
|
||||||
|
@ -131,8 +132,8 @@ class BraveAutoConfigurationTests {
|
||||||
this.contextRunner.run((context) -> {
|
this.contextRunner.run((context) -> {
|
||||||
assertThat(context).hasBean("propagationFactory");
|
assertThat(context).hasBean("propagationFactory");
|
||||||
Factory factory = context.getBean(Factory.class);
|
Factory factory = context.getBean(Factory.class);
|
||||||
List<Factory> injectors = getInjectors(factory);
|
Stream<Class<?>> injectors = getInjectors(factory).stream().map(Object::getClass);
|
||||||
assertThat(injectors).extracting(Factory::getClass).containsExactly(W3CPropagation.class);
|
assertThat(injectors).containsExactly(W3CPropagation.class);
|
||||||
assertThat(context).hasSingleBean(BaggagePropagation.FactoryBuilder.class);
|
assertThat(context).hasSingleBean(BaggagePropagation.FactoryBuilder.class);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -165,8 +166,8 @@ class BraveAutoConfigurationTests {
|
||||||
this.contextRunner.withPropertyValues("management.tracing.baggage.enabled=false").run((context) -> {
|
this.contextRunner.withPropertyValues("management.tracing.baggage.enabled=false").run((context) -> {
|
||||||
assertThat(context).hasBean("propagationFactory");
|
assertThat(context).hasBean("propagationFactory");
|
||||||
Factory factory = context.getBean(Factory.class);
|
Factory factory = context.getBean(Factory.class);
|
||||||
List<Factory> injectors = getInjectors(factory);
|
Stream<Class<?>> injectors = getInjectors(factory).stream().map(Object::getClass);
|
||||||
assertThat(injectors).extracting(Factory::getClass).containsExactly(W3CPropagation.class);
|
assertThat(injectors).containsExactly(W3CPropagation.class);
|
||||||
assertThat(context).doesNotHaveBean(BaggagePropagation.FactoryBuilder.class);
|
assertThat(context).doesNotHaveBean(BaggagePropagation.FactoryBuilder.class);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -270,7 +271,7 @@ class BraveAutoConfigurationTests {
|
||||||
private List<Factory> getInjectors(Factory factory) {
|
private List<Factory> getInjectors(Factory factory) {
|
||||||
assertThat(factory).as("factory").isNotNull();
|
assertThat(factory).as("factory").isNotNull();
|
||||||
if (factory instanceof CompositePropagationFactory compositePropagationFactory) {
|
if (factory instanceof CompositePropagationFactory compositePropagationFactory) {
|
||||||
return compositePropagationFactory.getInjectorFactories().stream().toList();
|
return compositePropagationFactory.getInjectors().toList();
|
||||||
}
|
}
|
||||||
Assertions.fail("Expected CompositePropagationFactory, found %s".formatted(factory.getClass()));
|
Assertions.fail("Expected CompositePropagationFactory, found %s".formatted(factory.getClass()));
|
||||||
throw new AssertionError("Unreachable");
|
throw new AssertionError("Unreachable");
|
||||||
|
|
|
@ -25,6 +25,7 @@ import brave.internal.propagation.StringPropagationAdapter;
|
||||||
import brave.propagation.Propagation;
|
import brave.propagation.Propagation;
|
||||||
import brave.propagation.TraceContext;
|
import brave.propagation.TraceContext;
|
||||||
import brave.propagation.TraceContextOrSamplingFlags;
|
import brave.propagation.TraceContextOrSamplingFlags;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
@ -39,63 +40,69 @@ import static org.mockito.BDDMockito.given;
|
||||||
*/
|
*/
|
||||||
class CompositePropagationFactoryTests {
|
class CompositePropagationFactoryTests {
|
||||||
|
|
||||||
@Test
|
|
||||||
void returnsAllKeys() {
|
|
||||||
CompositePropagationFactory factory = new CompositePropagationFactory(List.of(field("a")), List.of(field("b")));
|
|
||||||
assertThat(factory.keys()).containsExactly("a", "b");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void supportsJoin() {
|
void supportsJoin() {
|
||||||
Propagation.Factory supportsJoin = Mockito.mock(Propagation.Factory.class);
|
Propagation.Factory supported = Mockito.mock(Propagation.Factory.class);
|
||||||
given(supportsJoin.supportsJoin()).willReturn(true);
|
given(supported.supportsJoin()).willReturn(true);
|
||||||
given(supportsJoin.get()).willReturn(new DummyPropagation("a"));
|
given(supported.get()).willReturn(new DummyPropagation("a"));
|
||||||
Propagation.Factory doesNotSupportsJoin = Mockito.mock(Propagation.Factory.class);
|
Propagation.Factory unsupported = Mockito.mock(Propagation.Factory.class);
|
||||||
given(doesNotSupportsJoin.supportsJoin()).willReturn(false);
|
given(unsupported.supportsJoin()).willReturn(false);
|
||||||
given(doesNotSupportsJoin.get()).willReturn(new DummyPropagation("a"));
|
given(unsupported.get()).willReturn(new DummyPropagation("a"));
|
||||||
CompositePropagationFactory factory = new CompositePropagationFactory(List.of(supportsJoin),
|
CompositePropagationFactory factory = new CompositePropagationFactory(List.of(supported), List.of(unsupported));
|
||||||
List.of(doesNotSupportsJoin));
|
|
||||||
assertThat(factory.supportsJoin()).isFalse();
|
assertThat(factory.supportsJoin()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void requires128BitTraceId() {
|
void requires128BitTraceId() {
|
||||||
Propagation.Factory requires128BitTraceId = Mockito.mock(Propagation.Factory.class);
|
Propagation.Factory required = Mockito.mock(Propagation.Factory.class);
|
||||||
given(requires128BitTraceId.requires128BitTraceId()).willReturn(true);
|
given(required.requires128BitTraceId()).willReturn(true);
|
||||||
given(requires128BitTraceId.get()).willReturn(new DummyPropagation("a"));
|
given(required.get()).willReturn(new DummyPropagation("a"));
|
||||||
Propagation.Factory doesNotRequire128BitTraceId = Mockito.mock(Propagation.Factory.class);
|
Propagation.Factory notRequired = Mockito.mock(Propagation.Factory.class);
|
||||||
given(doesNotRequire128BitTraceId.requires128BitTraceId()).willReturn(false);
|
given(notRequired.requires128BitTraceId()).willReturn(false);
|
||||||
given(doesNotRequire128BitTraceId.get()).willReturn(new DummyPropagation("a"));
|
given(notRequired.get()).willReturn(new DummyPropagation("a"));
|
||||||
CompositePropagationFactory factory = new CompositePropagationFactory(List.of(requires128BitTraceId),
|
CompositePropagationFactory factory = new CompositePropagationFactory(List.of(required), List.of(notRequired));
|
||||||
List.of(doesNotRequire128BitTraceId));
|
|
||||||
assertThat(factory.requires128BitTraceId()).isTrue();
|
assertThat(factory.requires128BitTraceId()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
static class CompostePropagationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void keys() {
|
||||||
|
CompositePropagationFactory factory = new CompositePropagationFactory(List.of(field("a")),
|
||||||
|
List.of(field("b")));
|
||||||
|
Propagation<String> propagation = factory.get();
|
||||||
|
assertThat(propagation.keys()).containsExactly("a", "b");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void inject() {
|
void inject() {
|
||||||
CompositePropagationFactory factory = new CompositePropagationFactory(List.of(field("a"), field("b")),
|
CompositePropagationFactory factory = new CompositePropagationFactory(List.of(field("a"), field("b")),
|
||||||
List.of(field("c")));
|
List.of(field("c")));
|
||||||
|
Propagation<String> propagation = factory.get();
|
||||||
TraceContext context = context();
|
TraceContext context = context();
|
||||||
Map<String, String> request = new HashMap<>();
|
Map<String, String> request = new HashMap<>();
|
||||||
factory.injector(new MapSetter()).inject(context, request);
|
propagation.injector(new MapSetter()).inject(context, request);
|
||||||
assertThat(request).containsOnly(entry("a", "a-value"), entry("b", "b-value"));
|
assertThat(request).containsOnly(entry("a", "a-value"), entry("b", "b-value"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void extractorStopsAfterSuccessfulExtraction() {
|
void extractorWhenDelegateExtractsReturnsExtraction() {
|
||||||
CompositePropagationFactory factory = new CompositePropagationFactory(Collections.emptyList(),
|
CompositePropagationFactory factory = new CompositePropagationFactory(Collections.emptyList(),
|
||||||
List.of(field("a"), field("b")));
|
List.of(field("a"), field("b")));
|
||||||
|
Propagation<String> propagation = factory.get();
|
||||||
Map<String, String> request = Map.of("a", "a-value", "b", "b-value");
|
Map<String, String> request = Map.of("a", "a-value", "b", "b-value");
|
||||||
TraceContextOrSamplingFlags context = factory.extractor(new MapGetter()).extract(request);
|
TraceContextOrSamplingFlags context = propagation.extractor(new MapGetter()).extract(request);
|
||||||
assertThat(context.context().extra()).containsExactly("a");
|
assertThat(context.context().extra()).containsExactly("a");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void returnsEmptyContextWhenNoExtractorMatches() {
|
void extractorWhenWhenNoExtractorMatchesReturnsEmptyContext() {
|
||||||
CompositePropagationFactory factory = new CompositePropagationFactory(Collections.emptyList(),
|
CompositePropagationFactory factory = new CompositePropagationFactory(Collections.emptyList(),
|
||||||
Collections.emptyList());
|
Collections.emptyList());
|
||||||
|
Propagation<String> propagation = factory.get();
|
||||||
Map<String, String> request = Collections.emptyMap();
|
Map<String, String> request = Collections.emptyMap();
|
||||||
TraceContextOrSamplingFlags context = factory.extractor(new MapGetter()).extract(request);
|
TraceContextOrSamplingFlags context = propagation.extractor(new MapGetter()).extract(request);
|
||||||
assertThat(context.context()).isNull();
|
assertThat(context.context()).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +114,8 @@ class CompositePropagationFactoryTests {
|
||||||
return new DummyPropagation(field);
|
return new DummyPropagation(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static final class MapSetter implements Propagation.Setter<Map<String, String>, String> {
|
private static final class MapSetter implements Propagation.Setter<Map<String, String>, String> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -51,14 +51,14 @@ class CompositeTextMapPropagatorTests {
|
||||||
@Test
|
@Test
|
||||||
void collectsAllFields() {
|
void collectsAllFields() {
|
||||||
CompositeTextMapPropagator propagator = new CompositeTextMapPropagator(List.of(field("a")), List.of(field("b")),
|
CompositeTextMapPropagator propagator = new CompositeTextMapPropagator(List.of(field("a")), List.of(field("b")),
|
||||||
List.of(field("c")));
|
field("c"));
|
||||||
assertThat(propagator.fields()).containsExactly("a", "b", "c");
|
assertThat(propagator.fields()).containsExactly("a", "b", "c");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void injectAllFields() {
|
void injectAllFields() {
|
||||||
CompositeTextMapPropagator propagator = new CompositeTextMapPropagator(List.of(field("a"), field("b")),
|
CompositeTextMapPropagator propagator = new CompositeTextMapPropagator(List.of(field("a"), field("b")),
|
||||||
Collections.emptyList(), Collections.emptyList());
|
Collections.emptyList(), null);
|
||||||
TextMapSetter<Object> setter = setter();
|
TextMapSetter<Object> setter = setter();
|
||||||
Object carrier = carrier();
|
Object carrier = carrier();
|
||||||
propagator.inject(context(), carrier, setter);
|
propagator.inject(context(), carrier, setter);
|
||||||
|
@ -68,9 +68,9 @@ class CompositeTextMapPropagatorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void extractMutuallyExclusive() {
|
void extractWithoutBaggagePropagator() {
|
||||||
CompositeTextMapPropagator propagator = new CompositeTextMapPropagator(Collections.emptyList(),
|
CompositeTextMapPropagator propagator = new CompositeTextMapPropagator(Collections.emptyList(),
|
||||||
List.of(field("a"), field("b")), Collections.emptyList());
|
List.of(field("a"), field("b")), null);
|
||||||
Context context = context();
|
Context context = context();
|
||||||
Map<String, String> carrier = Map.of("a", "a-value", "b", "b-value");
|
Map<String, String> carrier = Map.of("a", "a-value", "b", "b-value");
|
||||||
context = propagator.extract(context, carrier, new MapTextMapGetter());
|
context = propagator.extract(context, carrier, new MapTextMapGetter());
|
||||||
|
@ -81,9 +81,9 @@ class CompositeTextMapPropagatorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void extractAlwaysRunning() {
|
void extractWithBaggagePropagator() {
|
||||||
CompositeTextMapPropagator propagator = new CompositeTextMapPropagator(Collections.emptyList(),
|
CompositeTextMapPropagator propagator = new CompositeTextMapPropagator(Collections.emptyList(),
|
||||||
List.of(field("a"), field("b")), List.of(field("c")));
|
List.of(field("a"), field("b")), field("c"));
|
||||||
Context context = context();
|
Context context = context();
|
||||||
Map<String, String> carrier = Map.of("a", "a-value", "b", "b-value", "c", "c-value");
|
Map<String, String> carrier = Map.of("a", "a-value", "b", "b-value", "c", "c-value");
|
||||||
context = propagator.extract(context, carrier, new MapTextMapGetter());
|
context = propagator.extract(context, carrier, new MapTextMapGetter());
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.springframework.boot.actuate.autoconfigure.tracing;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import io.micrometer.tracing.SpanCustomizer;
|
import io.micrometer.tracing.SpanCustomizer;
|
||||||
import io.micrometer.tracing.otel.bridge.OtelCurrentTraceContext;
|
import io.micrometer.tracing.otel.bridge.OtelCurrentTraceContext;
|
||||||
|
@ -174,9 +175,8 @@ class OpenTelemetryAutoConfigurationTests {
|
||||||
void shouldSupplyB3PropagationIfPropagationPropertySet() {
|
void shouldSupplyB3PropagationIfPropagationPropertySet() {
|
||||||
this.contextRunner.withPropertyValues("management.tracing.propagation.type=B3").run((context) -> {
|
this.contextRunner.withPropertyValues("management.tracing.propagation.type=B3").run((context) -> {
|
||||||
TextMapPropagator propagator = context.getBean(TextMapPropagator.class);
|
TextMapPropagator propagator = context.getBean(TextMapPropagator.class);
|
||||||
List<TextMapPropagator> injectors = getInjectors(propagator);
|
Stream<Class<?>> injectors = getInjectors(propagator).stream().map(Object::getClass);
|
||||||
assertThat(injectors).extracting(TextMapPropagator::getClass)
|
assertThat(injectors).containsExactly(B3Propagator.class, BaggageTextMapPropagator.class);
|
||||||
.containsExactly(B3Propagator.class, BaggageTextMapPropagator.class);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,8 +186,8 @@ class OpenTelemetryAutoConfigurationTests {
|
||||||
.withPropertyValues("management.tracing.propagation.type=B3", "management.tracing.baggage.enabled=false")
|
.withPropertyValues("management.tracing.propagation.type=B3", "management.tracing.baggage.enabled=false")
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
TextMapPropagator propagator = context.getBean(TextMapPropagator.class);
|
TextMapPropagator propagator = context.getBean(TextMapPropagator.class);
|
||||||
List<TextMapPropagator> injectors = getInjectors(propagator);
|
Stream<Class<?>> injectors = getInjectors(propagator).stream().map(Object::getClass);
|
||||||
assertThat(injectors).extracting(TextMapPropagator::getClass).containsExactly(B3Propagator.class);
|
assertThat(injectors).containsExactly(B3Propagator.class);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,9 +208,8 @@ class OpenTelemetryAutoConfigurationTests {
|
||||||
void shouldSupplyW3CPropagationWithoutBaggageWhenDisabled() {
|
void shouldSupplyW3CPropagationWithoutBaggageWhenDisabled() {
|
||||||
this.contextRunner.withPropertyValues("management.tracing.baggage.enabled=false").run((context) -> {
|
this.contextRunner.withPropertyValues("management.tracing.baggage.enabled=false").run((context) -> {
|
||||||
TextMapPropagator propagator = context.getBean(TextMapPropagator.class);
|
TextMapPropagator propagator = context.getBean(TextMapPropagator.class);
|
||||||
List<TextMapPropagator> injectors = getInjectors(propagator);
|
Stream<Class<?>> injectors = getInjectors(propagator).stream().map(Object::getClass);
|
||||||
assertThat(injectors).extracting(TextMapPropagator::getClass)
|
assertThat(injectors).containsExactly(W3CTraceContextPropagator.class);
|
||||||
.containsExactly(W3CTraceContextPropagator.class);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue