Skip to content

Commit 9b72cc4

Browse files
committed
Polish 'Add support for multiple tracing propagation formats'
See gh-35611
1 parent 691b549 commit 9b72cc4

File tree

9 files changed

+305
-297
lines changed

9 files changed

+305
-297
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,7 @@ static class BraveNoBaggageConfiguration {
167167
@Bean
168168
@ConditionalOnMissingBean
169169
Factory propagationFactory(TracingProperties properties) {
170-
return CompositePropagationFactory.create(properties.getPropagation().getEffectiveProducedTypes(),
171-
properties.getPropagation().getEffectiveConsumedTypes());
170+
return CompositePropagationFactory.create(properties.getPropagation(), null);
172171
}
173172

174173
}
@@ -187,10 +186,9 @@ static class BraveBaggageConfiguration {
187186
@ConditionalOnMissingBean
188187
BaggagePropagation.FactoryBuilder propagationFactoryBuilder(
189188
ObjectProvider<BaggagePropagationCustomizer> baggagePropagationCustomizers) {
190-
Factory delegate = CompositePropagationFactory.create(BRAVE_BAGGAGE_MANAGER,
191-
this.tracingProperties.getPropagation().getEffectiveProducedTypes(),
192-
this.tracingProperties.getPropagation().getEffectiveConsumedTypes());
193-
FactoryBuilder builder = BaggagePropagation.newFactoryBuilder(delegate);
189+
CompositePropagationFactory factory = CompositePropagationFactory
190+
.create(this.tracingProperties.getPropagation(), BRAVE_BAGGAGE_MANAGER);
191+
FactoryBuilder builder = BaggagePropagation.newFactoryBuilder(factory);
194192
baggagePropagationCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
195193
return builder;
196194
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/CompositePropagationFactory.java

Lines changed: 141 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -19,183 +19,206 @@
1919
import java.util.Collection;
2020
import java.util.Collections;
2121
import java.util.List;
22+
import java.util.function.Predicate;
2223
import java.util.stream.Stream;
2324

2425
import brave.internal.propagation.StringPropagationAdapter;
2526
import brave.propagation.B3Propagation;
2627
import brave.propagation.Propagation;
28+
import brave.propagation.Propagation.Factory;
2729
import brave.propagation.TraceContext;
2830
import brave.propagation.TraceContextOrSamplingFlags;
31+
import graphql.com.google.common.collect.Streams;
2932
import io.micrometer.tracing.BaggageManager;
3033
import io.micrometer.tracing.brave.bridge.W3CPropagation;
3134

35+
import org.springframework.boot.actuate.autoconfigure.tracing.TracingProperties.Propagation.PropagationType;
36+
3237
/**
33-
* {@link Factory} which supports multiple tracing formats. It is able to configure
34-
* different formats for injecting and for extracting.
38+
* {@link brave.propagation.Propagation.Factory Propagation factory} which supports
39+
* multiple tracing formats. It is able to configure different formats for injecting and
40+
* for extracting.
3541
*
3642
* @author Marcin Grzejszczak
3743
* @author Moritz Halbritter
44+
* @author Phillip Webb
3845
*/
39-
class CompositePropagationFactory extends Propagation.Factory implements Propagation<String> {
40-
41-
private final Collection<Propagation.Factory> injectorFactories;
42-
43-
private final Collection<Propagation.Factory> extractorFactories;
44-
45-
private final List<Propagation<String>> injectors;
46+
class CompositePropagationFactory extends Propagation.Factory {
4647

47-
private final List<Propagation<String>> extractors;
48+
private final PropagationFactories injectors;
4849

49-
private final boolean supportsJoin;
50+
private final PropagationFactories extractors;
5051

51-
private final boolean requires128BitTraceId;
52-
53-
private final List<String> keys;
52+
private final CompositePropagation propagation;
5453

5554
CompositePropagationFactory(Collection<Factory> injectorFactories, Collection<Factory> extractorFactories) {
56-
this.injectorFactories = injectorFactories;
57-
this.extractorFactories = extractorFactories;
58-
this.injectors = this.injectorFactories.stream().map(Factory::get).toList();
59-
this.extractors = this.extractorFactories.stream().map(Factory::get).toList();
60-
this.supportsJoin = Stream.concat(this.injectorFactories.stream(), this.extractorFactories.stream())
61-
.allMatch(Factory::supportsJoin);
62-
this.requires128BitTraceId = Stream.concat(this.injectorFactories.stream(), this.extractorFactories.stream())
63-
.anyMatch(Factory::requires128BitTraceId);
64-
this.keys = Stream.concat(this.injectors.stream(), this.extractors.stream())
65-
.flatMap((entry) -> entry.keys().stream())
66-
.distinct()
67-
.toList();
68-
}
69-
70-
Collection<Factory> getInjectorFactories() {
71-
return this.injectorFactories;
55+
this.injectors = new PropagationFactories(injectorFactories);
56+
this.extractors = new PropagationFactories(extractorFactories);
57+
this.propagation = new CompositePropagation(this.injectors, this.extractors);
7258
}
7359

74-
@Override
75-
public List<String> keys() {
76-
return this.keys;
60+
Stream<Factory> getInjectors() {
61+
return this.injectors.stream();
7762
}
7863

7964
@Override
80-
public <R> TraceContext.Injector<R> injector(Setter<R, String> setter) {
81-
return (traceContext, request) -> {
82-
for (Propagation<String> injector : this.injectors) {
83-
injector.injector(setter).inject(traceContext, request);
84-
}
85-
};
65+
public boolean supportsJoin() {
66+
return this.injectors.supportsJoin() && this.extractors.supportsJoin();
8667
}
8768

8869
@Override
89-
public <R> TraceContext.Extractor<R> extractor(Getter<R, String> getter) {
90-
return (request) -> {
91-
for (Propagation<String> extractor : this.extractors) {
92-
TraceContextOrSamplingFlags extract = extractor.extractor(getter).extract(request);
93-
if (extract != TraceContextOrSamplingFlags.EMPTY) {
94-
return extract;
95-
}
96-
}
97-
return TraceContextOrSamplingFlags.EMPTY;
98-
};
70+
public boolean requires128BitTraceId() {
71+
return this.injectors.requires128BitTraceId() || this.extractors.requires128BitTraceId();
9972
}
10073

10174
@Override
10275
@SuppressWarnings("deprecation")
103-
public <K> Propagation<K> create(KeyFactory<K> keyFactory) {
104-
return StringPropagationAdapter.create(this, keyFactory);
105-
}
106-
107-
@Override
108-
public boolean supportsJoin() {
109-
return this.supportsJoin;
110-
}
111-
112-
@Override
113-
public boolean requires128BitTraceId() {
114-
return this.requires128BitTraceId;
76+
public <K> Propagation<K> create(Propagation.KeyFactory<K> keyFactory) {
77+
return StringPropagationAdapter.create(this.propagation, keyFactory);
11578
}
11679

11780
@Override
11881
public TraceContext decorate(TraceContext context) {
119-
for (Factory injectorFactory : this.injectorFactories) {
120-
TraceContext decorated = injectorFactory.decorate(context);
121-
if (decorated != context) {
122-
return decorated;
123-
}
124-
}
125-
for (Factory extractorFactory : this.extractorFactories) {
126-
TraceContext decorated = extractorFactory.decorate(context);
127-
if (decorated != context) {
128-
return decorated;
129-
}
130-
}
131-
return super.decorate(context);
82+
return Streams.concat(this.injectors.stream(), this.extractors.stream())
83+
.map((factory) -> factory.decorate(context))
84+
.filter((decorated) -> decorated != context)
85+
.findFirst()
86+
.orElse(context);
13287
}
13388

13489
/**
13590
* Creates a new {@link CompositePropagationFactory}, which uses the given
13691
* {@code injectionTypes} for injection and {@code extractionTypes} for extraction.
92+
* @param properties the propagation properties
13793
* @param baggageManager the baggage manager to use, or {@code null}
138-
* @param injectionTypes the propagation types for injection
139-
* @param extractionTypes the propagation types for extraction
14094
* @return the {@link CompositePropagationFactory}
14195
*/
142-
static CompositePropagationFactory create(BaggageManager baggageManager,
143-
Collection<TracingProperties.Propagation.PropagationType> injectionTypes,
144-
Collection<TracingProperties.Propagation.PropagationType> extractionTypes) {
145-
List<Factory> injectors = injectionTypes.stream()
146-
.map((injection) -> factoryForType(baggageManager, injection))
147-
.toList();
148-
List<Factory> extractors = extractionTypes.stream()
149-
.map((extraction) -> factoryForType(baggageManager, extraction))
150-
.toList();
96+
static CompositePropagationFactory create(TracingProperties.Propagation properties, BaggageManager baggageManager) {
97+
PropagationFactoryMapper mapper = new PropagationFactoryMapper(baggageManager);
98+
List<Factory> injectors = properties.getEffectiveProducedTypes().stream().map(mapper::map).toList();
99+
List<Factory> extractors = properties.getEffectiveConsumedTypes().stream().map(mapper::map).toList();
151100
return new CompositePropagationFactory(injectors, extractors);
152101
}
153102

154103
/**
155-
* Creates a new {@link CompositePropagationFactory}, which uses the given
156-
* {@code injectionTypes} for injection and {@code extractionTypes} for extraction.
157-
* @param injectionTypes the propagation types for injection
158-
* @param extractionTypes the propagation types for extraction
159-
* @return the {@link CompositePropagationFactory}
104+
* Mapper used to create a {@link brave.propagation.Propagation.Factory Propagation
105+
* factory} from a {@link PropagationType}.
160106
*/
161-
static CompositePropagationFactory create(Collection<TracingProperties.Propagation.PropagationType> injectionTypes,
162-
Collection<TracingProperties.Propagation.PropagationType> extractionTypes) {
163-
return create(null, injectionTypes, extractionTypes);
164-
}
107+
private static class PropagationFactoryMapper {
165108

166-
private static Factory factoryForType(BaggageManager baggageManager,
167-
TracingProperties.Propagation.PropagationType type) {
168-
return switch (type) {
169-
case B3 -> b3Single();
170-
case B3_MULTI -> b3Multi();
171-
case W3C -> w3c(baggageManager);
172-
};
173-
}
109+
private final BaggageManager baggageManager;
110+
111+
PropagationFactoryMapper(BaggageManager baggageManager) {
112+
this.baggageManager = baggageManager;
113+
}
114+
115+
Propagation.Factory map(PropagationType type) {
116+
return switch (type) {
117+
case B3 -> b3Single();
118+
case B3_MULTI -> b3Multi();
119+
case W3C -> w3c();
120+
};
121+
}
122+
123+
/**
124+
* Creates a new B3 propagation factory using a single B3 header.
125+
* @return the B3 propagation factory
126+
*/
127+
private Propagation.Factory b3Single() {
128+
return B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.SINGLE_NO_PARENT).build();
129+
}
130+
131+
/**
132+
* Creates a new B3 propagation factory using multiple B3 headers.
133+
* @return the B3 propagation factory
134+
*/
135+
private Propagation.Factory b3Multi() {
136+
return B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.MULTI).build();
137+
}
138+
139+
/**
140+
* Creates a new W3C propagation factory.
141+
* @return the W3C propagation factory
142+
*/
143+
private Propagation.Factory w3c() {
144+
return (this.baggageManager != null) ? new W3CPropagation(this.baggageManager, Collections.emptyList())
145+
: new W3CPropagation();
146+
}
174147

175-
/**
176-
* Creates a new B3 propagation factory using a single B3 header.
177-
* @return the B3 propagation factory
178-
*/
179-
private static Factory b3Single() {
180-
return B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.SINGLE_NO_PARENT).build();
181148
}
182149

183150
/**
184-
* Creates a new B3 propagation factory using multiple B3 headers.
185-
* @return the B3 propagation factory
151+
* A collection of propagation factories.
186152
*/
187-
private static Factory b3Multi() {
188-
return B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.MULTI).build();
153+
private static class PropagationFactories {
154+
155+
private final List<Propagation.Factory> factories;
156+
157+
PropagationFactories(Collection<Factory> factories) {
158+
this.factories = List.copyOf(factories);
159+
}
160+
161+
boolean requires128BitTraceId() {
162+
return stream().anyMatch(Propagation.Factory::requires128BitTraceId);
163+
}
164+
165+
boolean supportsJoin() {
166+
return stream().allMatch(Propagation.Factory::supportsJoin);
167+
}
168+
169+
List<Propagation<String>> get() {
170+
return stream().map(Factory::get).toList();
171+
}
172+
173+
Stream<Factory> stream() {
174+
return this.factories.stream();
175+
}
176+
189177
}
190178

191179
/**
192-
* Creates a new W3C propagation factory.
193-
* @param baggageManager baggage manager to use, or {@code null}
194-
* @return the W3C propagation factory
180+
* A composite {@link Propagation}.
195181
*/
196-
private static W3CPropagation w3c(BaggageManager baggageManager) {
197-
return (baggageManager != null) ? new W3CPropagation(baggageManager, Collections.emptyList())
198-
: new W3CPropagation();
182+
private static class CompositePropagation implements Propagation<String> {
183+
184+
private final List<Propagation<String>> injectors;
185+
186+
private final List<Propagation<String>> extractors;
187+
188+
private final List<String> keys;
189+
190+
CompositePropagation(PropagationFactories injectorFactories, PropagationFactories extractorFactories) {
191+
this.injectors = injectorFactories.get();
192+
this.extractors = extractorFactories.get();
193+
this.keys = Stream.concat(keys(this.injectors), keys(this.extractors)).distinct().toList();
194+
}
195+
196+
private Stream<String> keys(List<Propagation<String>> propagations) {
197+
return propagations.stream().flatMap((propagation) -> propagation.keys().stream());
198+
}
199+
200+
@Override
201+
public List<String> keys() {
202+
return this.keys;
203+
}
204+
205+
@Override
206+
public <R> TraceContext.Injector<R> injector(Setter<R, String> setter) {
207+
return (traceContext, request) -> this.injectors.stream()
208+
.map((propagation) -> propagation.injector(setter))
209+
.forEach((injector) -> injector.inject(traceContext, request));
210+
}
211+
212+
@Override
213+
public <R> TraceContext.Extractor<R> extractor(Getter<R, String> getter) {
214+
return (request) -> this.extractors.stream()
215+
.map((propagation) -> propagation.extractor(getter))
216+
.map((extractor) -> extractor.extract(request))
217+
.filter(Predicate.not(TraceContextOrSamplingFlags.EMPTY::equals))
218+
.findFirst()
219+
.orElse(TraceContextOrSamplingFlags.EMPTY);
220+
}
221+
199222
}
200223

201224
}

0 commit comments

Comments
 (0)