This change adds support for multiple context propagation types (e.g. B3 and W3C). It also adds support for a new propagation type, B3_MULTI (which is B3 with multiple headers instead of the single b3 header).
There are now two new properties:
management.tracing.propagation.consumewhich controls which trace formats the application will understand on incoming requests. It defaults to all known trace formats (W3C, B3 single, B3 multi).management.tracing.propagation.producewhich controls which trace formats the application will add to outgoing requests. It defaults to W3C.
The management.tracing.propagation.type has been changed from PropagationType to List<PropagationType> and the default has been removed. If set, this will override both management.tracing.propagation.consume and management.tracing.propagation.produce.
The formats have an ordering, meaning that if one of the extractors matches, the one after it are no longer considered. The default ordering is:
- W3C
- B3 single
- B3 multi
The CompositePropagationFactory is the main piece of code for Brave which knows how to extract and inject multiple formats. It's a copy from Sleuth, somewhat refactored.
The CompositeTextMapPropagator is the main piece of code for OTel. It's somewhat more complicated than the Brave pendant as we need to support the BaggageTextMapPropagator which must run always even if one of the extractors before it has already extracted the context.
I also removed a @ConditionalOnMissingBean for type B3Propagator and W3CTraceContextPropagator. This should be fine as it's not consistent anyway. In the bagagge = true case those @ConditionalOnMissingBean are not effective but the extractors are added unconditionally in w3cTextMapPropagatorWithBaggage and b3BaggageTextMapPropagator.
Property examples
- To only use B3 single, set
management.tracing.propagation.typetoB3 - To only use B3 multi, set
management.tracing.propagation.typetoB3_MULTI -
To only use W3C multi, set
management.tracing.propagation.typetoW3C -
To produce B3 single and W3C and accept W3C, B3 single and multi, set
management.tracing.propagation.producetoB3,W3Candmanagement.tracing.propagation.consumetoB3,B3_MULTI,W3C
See gh-35096
Comment From: mhalbritter
It works for both Brave and Otel now, build is green too.
Comment From: mhalbritter
When merging into 3.1.x, the test BraveAutoConfigurationTests.shouldSupportJoinedSpansIfB3UsedAndBackendSupportsIt fails. That's because it expects that span joining is supported when using B3. However, as we now extract all formats from the incoming request, CompositePropagationFactory.supportsJoin always returns false, as there is a W3CPropagation in the extractor list and it doesn't support joins. CompositePropagationFactory.supportJoin is implemented like this:
Stream.concat(injectorFactories.stream(), extractorFactories.stream()).allMatch(Factory::supportsJoin);
Is that just an unfortunate consequence because we now apply all extractors, or is the span joining feature just for injecting and the supportJoin should be changed to only work on the injectorFactories?
@jonatan-ivanov As you implemented the test / feature, maybe you have an idea?
If that's an unfortunate consequence and can't be changed, do we need a way to opt out of extracting all known formats? With that, users could configure B3 only for injecting and extracting, and span joining works again. Maybe by adding a property management.tracing.propagation.consume-types of type List<PropagationType> which defaults to PropagationType.values() (all known types)?
Comment From: jonatan-ivanov
Yeah, if we consume all formats by default supportsJoin won't work, I completely missed this when we discussed this issue, I'm sorry.
I think letting the users define the consumed formats would work. I'm also thinking if we should set the right formats if supportsJoin=true. That might be a little shady side effect though.
Comment From: mhalbritter
No worries Jonatan. I've now added properties to control which formats we produce, which we accept and the management.tracing.propagation.type controls both at the same time.
management.tracing.propagation.type no longer has a default. If set, it overrides management.tracing.propagation.consume-types and management.tracing.propagation.produce-types.
With that in place, we should have enough flexibility in our tracing setup. And users still have one property management.tracing.propagation.type if they aren't interested in configuring the low-level details.
Comment From: wilkinsona
management.tracing.propagation.consume-typesandmanagement.tracing.propagation.produce-types
Alternative names for these properties to consider:
management.tracing.propagation.consumeandmanagement.tracing.propagation.producemanagement.tracing.propagation.types.consumeandmanagement.tracing.propagation.types.produce
Comment From: mhalbritter
I've settled on management.tracing.propagation.consume and management.tracing.propagation.produce. This gets rid of the dash and reads cleaner.
Comment From: mhalbritter
And it's a merge! Thank you all for providing input!