Merge pull request #32480 from marcingrzejszczak
* gh-32480: Polish "Add support for MDC, Context Propagation (via B3 and W3C), and Baggage" Add support for MDC, Context Propagation (via B3 and W3C), and Baggage Closes gh-32480
This commit is contained in:
commit
3acd9b80e8
|
|
@ -22,6 +22,15 @@ import brave.Tracer;
|
|||
import brave.Tracing;
|
||||
import brave.Tracing.Builder;
|
||||
import brave.TracingCustomizer;
|
||||
import brave.baggage.BaggageField;
|
||||
import brave.baggage.BaggagePropagation;
|
||||
import brave.baggage.BaggagePropagation.FactoryBuilder;
|
||||
import brave.baggage.BaggagePropagationConfig;
|
||||
import brave.baggage.BaggagePropagationCustomizer;
|
||||
import brave.baggage.CorrelationScopeConfig;
|
||||
import brave.baggage.CorrelationScopeCustomizer;
|
||||
import brave.baggage.CorrelationScopeDecorator;
|
||||
import brave.context.slf4j.MDCScopeDecorator;
|
||||
import brave.handler.SpanHandler;
|
||||
import brave.http.HttpClientHandler;
|
||||
import brave.http.HttpClientRequest;
|
||||
|
|
@ -41,20 +50,27 @@ import io.micrometer.tracing.brave.bridge.BraveBaggageManager;
|
|||
import io.micrometer.tracing.brave.bridge.BraveCurrentTraceContext;
|
||||
import io.micrometer.tracing.brave.bridge.BraveHttpClientHandler;
|
||||
import io.micrometer.tracing.brave.bridge.BraveHttpServerHandler;
|
||||
import io.micrometer.tracing.brave.bridge.BravePropagator;
|
||||
import io.micrometer.tracing.brave.bridge.BraveTracer;
|
||||
import io.micrometer.tracing.brave.bridge.W3CPropagation;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Brave.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@AutoConfiguration(before = MicrometerTracingAutoConfiguration.class)
|
||||
|
|
@ -63,6 +79,8 @@ import org.springframework.core.env.Environment;
|
|||
@ConditionalOnEnabledTracing
|
||||
public class BraveAutoConfiguration {
|
||||
|
||||
private static final BraveBaggageManager BRAVE_BAGGAGE_MANAGER = new BraveBaggageManager();
|
||||
|
||||
/**
|
||||
* Default value for application name if {@code spring.application.name} is not set.
|
||||
*/
|
||||
|
|
@ -105,12 +123,6 @@ public class BraveAutoConfiguration {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public Factory bravePropagationFactory() {
|
||||
return B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.SINGLE_NO_PARENT).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public Sampler braveSampler(TracingProperties properties) {
|
||||
|
|
@ -137,15 +149,14 @@ public class BraveAutoConfiguration {
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
BraveTracer braveTracerBridge(brave.Tracer tracer, CurrentTraceContext currentTraceContext,
|
||||
BraveBaggageManager braveBaggageManager) {
|
||||
return new BraveTracer(tracer, new BraveCurrentTraceContext(currentTraceContext), braveBaggageManager);
|
||||
BraveTracer braveTracerBridge(brave.Tracer tracer, CurrentTraceContext currentTraceContext) {
|
||||
return new BraveTracer(tracer, new BraveCurrentTraceContext(currentTraceContext), BRAVE_BAGGAGE_MANAGER);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
BraveBaggageManager braveBaggageManager() {
|
||||
return new BraveBaggageManager();
|
||||
BravePropagator bravePropagator(Tracing tracing) {
|
||||
return new BravePropagator(tracing);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
@ -162,4 +173,92 @@ public class BraveAutoConfiguration {
|
|||
return new BraveHttpClientHandler(httpClientHandler);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(value = "management.tracing.baggage.enabled", havingValue = "false")
|
||||
static class BraveNoBaggageConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
Factory propagationFactory(TracingProperties tracing) {
|
||||
return switch (tracing.getPropagation().getType()) {
|
||||
case B3 ->
|
||||
B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.SINGLE_NO_PARENT).build();
|
||||
case W3C -> new W3CPropagation(BRAVE_BAGGAGE_MANAGER, List.of());
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(value = "management.tracing.baggage.enabled", matchIfMissing = true)
|
||||
static class BraveBaggageConfiguration {
|
||||
|
||||
private final TracingProperties tracingProperties;
|
||||
|
||||
BraveBaggageConfiguration(TracingProperties tracingProperties) {
|
||||
this.tracingProperties = tracingProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
BaggagePropagation.FactoryBuilder propagationFactoryBuilder(
|
||||
ObjectProvider<BaggagePropagationCustomizer> baggagePropagationCustomizers) {
|
||||
Factory delegate = switch (this.tracingProperties.getPropagation().getType()) {
|
||||
case B3 ->
|
||||
B3Propagation.newFactoryBuilder().injectFormat(B3Propagation.Format.SINGLE_NO_PARENT).build();
|
||||
case W3C -> new W3CPropagation(BRAVE_BAGGAGE_MANAGER, List.of());
|
||||
};
|
||||
FactoryBuilder builder = BaggagePropagation.newFactoryBuilder(delegate);
|
||||
baggagePropagationCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(0)
|
||||
BaggagePropagationCustomizer remoteFieldsBaggagePropagationCustomizer() {
|
||||
return (builder) -> {
|
||||
List<String> remoteFields = this.tracingProperties.getBaggage().getRemoteFields();
|
||||
for (String fieldName : remoteFields) {
|
||||
builder.add(BaggagePropagationConfig.SingleBaggageField.remote(BaggageField.create(fieldName)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
Factory propagationFactory(BaggagePropagation.FactoryBuilder factoryBuilder) {
|
||||
return factoryBuilder.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
CorrelationScopeDecorator.Builder mdcCorrelationScopeDecoratorBuilder(
|
||||
ObjectProvider<CorrelationScopeCustomizer> correlationScopeCustomizers) {
|
||||
CorrelationScopeDecorator.Builder builder = MDCScopeDecorator.newBuilder();
|
||||
correlationScopeCustomizers.forEach((customizer) -> customizer.customize(builder));
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(0)
|
||||
@ConditionalOnProperty(prefix = "management.tracing.baggage.correlation", name = "enabled",
|
||||
matchIfMissing = true)
|
||||
CorrelationScopeCustomizer correlationFieldsCorrelationScopeCustomizer() {
|
||||
return (builder) -> {
|
||||
List<String> correlationFields = this.tracingProperties.getBaggage().getCorrelation().getFields();
|
||||
for (String field : correlationFields) {
|
||||
builder.add(CorrelationScopeConfig.SingleCorrelationField.newBuilder(BaggageField.create(field))
|
||||
.flushOnUpdate().build());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(CorrelationScopeDecorator.class)
|
||||
ScopeDecorator correlationScopeDecorator(CorrelationScopeDecorator.Builder builder) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,17 +23,27 @@ import java.util.stream.Collectors;
|
|||
import io.micrometer.tracing.SamplerFunction;
|
||||
import io.micrometer.tracing.otel.bridge.DefaultHttpClientAttributesGetter;
|
||||
import io.micrometer.tracing.otel.bridge.DefaultHttpServerAttributesExtractor;
|
||||
import io.micrometer.tracing.otel.bridge.EventListener;
|
||||
import io.micrometer.tracing.otel.bridge.EventPublishingContextWrapper;
|
||||
import io.micrometer.tracing.otel.bridge.OtelBaggageManager;
|
||||
import io.micrometer.tracing.otel.bridge.OtelCurrentTraceContext;
|
||||
import io.micrometer.tracing.otel.bridge.OtelHttpClientHandler;
|
||||
import io.micrometer.tracing.otel.bridge.OtelHttpServerHandler;
|
||||
import io.micrometer.tracing.otel.bridge.OtelPropagator;
|
||||
import io.micrometer.tracing.otel.bridge.OtelTracer;
|
||||
import io.micrometer.tracing.otel.bridge.OtelTracer.EventPublisher;
|
||||
import io.micrometer.tracing.otel.bridge.Slf4JBaggageEventListener;
|
||||
import io.micrometer.tracing.otel.bridge.Slf4JEventListener;
|
||||
import io.micrometer.tracing.otel.propagation.BaggageTextMapPropagator;
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.trace.Tracer;
|
||||
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
|
||||
import io.opentelemetry.context.ContextStorage;
|
||||
import io.opentelemetry.context.propagation.ContextPropagators;
|
||||
import io.opentelemetry.context.propagation.TextMapPropagator;
|
||||
import io.opentelemetry.extension.trace.propagation.B3Propagator;
|
||||
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.sdk.trace.SdkTracerProvider;
|
||||
|
|
@ -44,13 +54,16 @@ import io.opentelemetry.sdk.trace.export.SpanExporter;
|
|||
import io.opentelemetry.sdk.trace.samplers.Sampler;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.SpringBootVersion;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
|
|
@ -70,6 +83,12 @@ public class OpenTelemetryAutoConfiguration {
|
|||
*/
|
||||
private static final String DEFAULT_APPLICATION_NAME = "application";
|
||||
|
||||
private final TracingProperties tracingProperties;
|
||||
|
||||
OpenTelemetryAutoConfiguration(TracingProperties tracingProperties) {
|
||||
this.tracingProperties = tracingProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
OpenTelemetry openTelemetry(SdkTracerProvider sdkTracerProvider, ContextPropagators contextPropagators) {
|
||||
|
|
@ -79,33 +98,31 @@ public class OpenTelemetryAutoConfiguration {
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
SdkTracerProvider otelSdkTracerProvider(Environment environment, List<SpanProcessor> spanProcessors,
|
||||
SdkTracerProvider otelSdkTracerProvider(Environment environment, ObjectProvider<SpanProcessor> spanProcessors,
|
||||
Sampler sampler) {
|
||||
String applicationName = environment.getProperty("spring.application.name", DEFAULT_APPLICATION_NAME);
|
||||
SdkTracerProviderBuilder builder = SdkTracerProvider.builder().setSampler(sampler)
|
||||
.setResource(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, applicationName)));
|
||||
for (SpanProcessor spanProcessor : spanProcessors) {
|
||||
builder.addSpanProcessor(spanProcessor);
|
||||
}
|
||||
spanProcessors.orderedStream().forEach(builder::addSpanProcessor);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
ContextPropagators otelContextPropagators(List<TextMapPropagator> textMapPropagators) {
|
||||
return ContextPropagators.create(TextMapPropagator.composite(textMapPropagators));
|
||||
ContextPropagators otelContextPropagators(ObjectProvider<TextMapPropagator> textMapPropagators) {
|
||||
return ContextPropagators
|
||||
.create(TextMapPropagator.composite(textMapPropagators.orderedStream().collect(Collectors.toList())));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
Sampler otelSampler(TracingProperties properties) {
|
||||
return Sampler.traceIdRatioBased(properties.getSampling().getProbability());
|
||||
Sampler otelSampler() {
|
||||
return Sampler.traceIdRatioBased(this.tracingProperties.getSampling().getProbability());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
SpanProcessor otelSpanProcessor(List<SpanExporter> spanExporter) {
|
||||
return SpanProcessor.composite(spanExporter.stream()
|
||||
SpanProcessor otelSpanProcessor(ObjectProvider<SpanExporter> spanExporters) {
|
||||
return SpanProcessor.composite(spanExporters.orderedStream()
|
||||
.map((exporter) -> BatchSpanProcessor.builder(exporter).build()).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
|
|
@ -119,20 +136,26 @@ public class OpenTelemetryAutoConfiguration {
|
|||
@ConditionalOnMissingBean
|
||||
OtelTracer micrometerOtelTracer(Tracer tracer, EventPublisher eventPublisher,
|
||||
OtelCurrentTraceContext otelCurrentTraceContext) {
|
||||
return new OtelTracer(tracer, otelCurrentTraceContext, eventPublisher,
|
||||
new OtelBaggageManager(otelCurrentTraceContext, List.of(), List.of()));
|
||||
return new OtelTracer(tracer, otelCurrentTraceContext, eventPublisher, new OtelBaggageManager(
|
||||
otelCurrentTraceContext, this.tracingProperties.getBaggage().getRemoteFields(), List.of()));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
EventPublisher otelTracerEventPublisher() {
|
||||
return (event) -> {
|
||||
};
|
||||
OtelPropagator otelPropagator(ContextPropagators contextPropagators, Tracer tracer) {
|
||||
return new OtelPropagator(contextPropagators, tracer);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
OtelCurrentTraceContext otelCurrentTraceContext() {
|
||||
EventPublisher otelTracerEventPublisher(List<EventListener> eventListeners) {
|
||||
return new OTelEventPublisher(eventListeners);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
OtelCurrentTraceContext otelCurrentTraceContext(EventPublisher publisher) {
|
||||
ContextStorage.addWrapper(new EventPublishingContextWrapper(publisher));
|
||||
return new OtelCurrentTraceContext();
|
||||
}
|
||||
|
||||
|
|
@ -150,4 +173,84 @@ public class OpenTelemetryAutoConfiguration {
|
|||
new DefaultHttpServerAttributesExtractor());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
Slf4JEventListener otelSlf4JEventListener() {
|
||||
return new Slf4JEventListener();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(prefix = "management.tracing.baggage", name = "enabled", matchIfMissing = true)
|
||||
static class BaggageConfiguration {
|
||||
|
||||
private final TracingProperties tracingProperties;
|
||||
|
||||
BaggageConfiguration(TracingProperties tracingProperties) {
|
||||
this.tracingProperties = tracingProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "management.tracing.propagation", name = "type", havingValue = "W3C",
|
||||
matchIfMissing = true)
|
||||
TextMapPropagator w3cTextMapPropagatorWithBaggage() {
|
||||
return TextMapPropagator.composite(W3CTraceContextPropagator.getInstance(),
|
||||
W3CBaggagePropagator.getInstance());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "management.tracing.propagation", name = "type", havingValue = "B3")
|
||||
TextMapPropagator b3BaggageTextMapPropagator(OtelCurrentTraceContext otelCurrentTraceContext) {
|
||||
List<String> remoteFields = this.tracingProperties.getBaggage().getRemoteFields();
|
||||
return TextMapPropagator.composite(B3Propagator.injectingSingleHeader(), new BaggageTextMapPropagator(
|
||||
remoteFields, new OtelBaggageManager(otelCurrentTraceContext, remoteFields, List.of())));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(prefix = "management.tracing.baggage.correlation", name = "enabled",
|
||||
matchIfMissing = true)
|
||||
Slf4JBaggageEventListener otelSlf4JBaggageEventListener() {
|
||||
return new Slf4JBaggageEventListener(this.tracingProperties.getBaggage().getCorrelation().getFields());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(prefix = "management.tracing.baggage", name = "enabled", havingValue = "false")
|
||||
static class NoBaggageConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(prefix = "management.tracing.propagation", name = "type", havingValue = "B3")
|
||||
B3Propagator b3TextMapPropagator() {
|
||||
return B3Propagator.injectingSingleHeader();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(prefix = "management.tracing.propagation", name = "type", havingValue = "W3C",
|
||||
matchIfMissing = true)
|
||||
W3CTraceContextPropagator w3cTextMapPropagatorWithoutBaggage() {
|
||||
return W3CTraceContextPropagator.getInstance();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class OTelEventPublisher implements EventPublisher {
|
||||
|
||||
private final List<EventListener> listeners;
|
||||
|
||||
OTelEventPublisher(List<EventListener> listeners) {
|
||||
this.listeners = listeners;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishEvent(Object event) {
|
||||
for (EventListener listener : this.listeners) {
|
||||
listener.onEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
package org.springframework.boot.actuate.autoconfigure.tracing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
|
|
@ -32,10 +35,28 @@ public class TracingProperties {
|
|||
*/
|
||||
private final Sampling sampling = new Sampling();
|
||||
|
||||
/**
|
||||
* Baggage configuration.
|
||||
*/
|
||||
private final Baggage baggage = new Baggage();
|
||||
|
||||
/**
|
||||
* Propagation configuration.
|
||||
*/
|
||||
private final Propagation propagation = new Propagation();
|
||||
|
||||
public Sampling getSampling() {
|
||||
return this.sampling;
|
||||
}
|
||||
|
||||
public Baggage getBaggage() {
|
||||
return this.baggage;
|
||||
}
|
||||
|
||||
public Propagation getPropagation() {
|
||||
return this.propagation;
|
||||
}
|
||||
|
||||
public static class Sampling {
|
||||
|
||||
/**
|
||||
|
|
@ -53,4 +74,111 @@ public class TracingProperties {
|
|||
|
||||
}
|
||||
|
||||
public static class Baggage {
|
||||
|
||||
/**
|
||||
* Whether to enable Micrometer Tracing baggage propagation.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* Correlation configuration.
|
||||
*/
|
||||
private Correlation correlation = new Correlation();
|
||||
|
||||
/**
|
||||
* List of fields that are referenced the same in-process as it is on the wire.
|
||||
* For example, the field "x-vcap-request-id" would be set as-is including the
|
||||
* prefix.
|
||||
*/
|
||||
private List<String> remoteFields = new ArrayList<>();
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public Correlation getCorrelation() {
|
||||
return this.correlation;
|
||||
}
|
||||
|
||||
public void setCorrelation(Correlation correlation) {
|
||||
this.correlation = correlation;
|
||||
}
|
||||
|
||||
public List<String> getRemoteFields() {
|
||||
return this.remoteFields;
|
||||
}
|
||||
|
||||
public void setRemoteFields(List<String> remoteFields) {
|
||||
this.remoteFields = remoteFields;
|
||||
}
|
||||
|
||||
public static class Correlation {
|
||||
|
||||
/**
|
||||
* Whether to enable correlation of the baggage context with logging contexts.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* List of fields that should be correlated with the logging context. That
|
||||
* means that these fields would end up as key-value pairs in e.g. MDC.
|
||||
*/
|
||||
private List<String> fields = new ArrayList<>();
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public List<String> getFields() {
|
||||
return this.fields;
|
||||
}
|
||||
|
||||
public void setFields(List<String> fields) {
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Propagation {
|
||||
|
||||
/**
|
||||
* Tracing context propagation types.
|
||||
*/
|
||||
private PropagationType type = PropagationType.W3C;
|
||||
|
||||
public PropagationType getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public void setType(PropagationType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
enum PropagationType {
|
||||
|
||||
/**
|
||||
* B3 propagation type.
|
||||
*/
|
||||
B3,
|
||||
|
||||
/**
|
||||
* W3C propagation type.
|
||||
*/
|
||||
W3C
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2086,6 +2086,10 @@
|
|||
"replacement": "management.trace.http.include",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.tracing.propagation.type",
|
||||
"defaultValue": "W3C"
|
||||
}
|
||||
],
|
||||
"hints": [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright 2012-2022 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.boot.actuate.autoconfigure.tracing;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import io.micrometer.tracing.BaggageInScope;
|
||||
import io.micrometer.tracing.BaggageManager;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import io.opentelemetry.context.Context;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for Baggage propagation with Brave and OpenTelemetry using W3C and B3 propagation
|
||||
* formats.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
class BaggagePropagationIntegrationTests {
|
||||
|
||||
static final String COUNTRY_CODE = "country-code";
|
||||
static final String BUSINESS_PROCESS = "bp";
|
||||
|
||||
@BeforeEach
|
||||
@AfterEach
|
||||
void setup() {
|
||||
MDC.clear();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(AutoConfig.class)
|
||||
void shouldSetEntriesToMdcFromSpanWithBaggage(AutoConfig autoConfig) {
|
||||
autoConfig.get().run((context) -> {
|
||||
Tracer tracer = tracer(context);
|
||||
Span span = createSpan(tracer);
|
||||
assertThatTracingContextIsInitialized(autoConfig);
|
||||
try (Tracer.SpanInScope scope = tracer.withSpan(span.start());
|
||||
BaggageInScope fo = context.getBean(BaggageManager.class).createBaggage(COUNTRY_CODE)
|
||||
.set(span.context(), "FO");
|
||||
BaggageInScope bp = context.getBean(BaggageManager.class).createBaggage(BUSINESS_PROCESS)
|
||||
.set(span.context(), "ALM")) {
|
||||
assertThat(MDC.get("traceId")).isEqualTo(span.context().traceId());
|
||||
assertThat(MDC.get(COUNTRY_CODE)).isEqualTo("FO");
|
||||
assertThat(MDC.get(BUSINESS_PROCESS)).isEqualTo("ALM");
|
||||
}
|
||||
finally {
|
||||
span.end();
|
||||
}
|
||||
|
||||
assertThatMdcContainsUnsetTraceId();
|
||||
assertThat(MDC.get(COUNTRY_CODE)).isNull();
|
||||
assertThat(MDC.get(BUSINESS_PROCESS)).isNull();
|
||||
});
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(AutoConfig.class)
|
||||
void shouldRemoveEntriesFromMdcForNullSpan(AutoConfig autoConfig) {
|
||||
autoConfig.get().run((context) -> {
|
||||
Tracer tracer = tracer(context);
|
||||
Span span = createSpan(tracer);
|
||||
assertThatTracingContextIsInitialized(autoConfig);
|
||||
try (Tracer.SpanInScope scope = tracer.withSpan(span.start());
|
||||
BaggageInScope fo = context.getBean(BaggageManager.class).createBaggage(COUNTRY_CODE)
|
||||
.set(span.context(), "FO")) {
|
||||
assertThat(MDC.get("traceId")).isEqualTo(span.context().traceId());
|
||||
assertThat(MDC.get(COUNTRY_CODE)).isEqualTo("FO");
|
||||
|
||||
try (Tracer.SpanInScope scope2 = tracer.withSpan(null)) {
|
||||
assertThatMdcContainsUnsetTraceId();
|
||||
assertThat(MDC.get(COUNTRY_CODE)).isNullOrEmpty();
|
||||
}
|
||||
|
||||
assertThat(MDC.get("traceId")).isEqualTo(span.context().traceId());
|
||||
assertThat(MDC.get(COUNTRY_CODE)).isEqualTo("FO");
|
||||
}
|
||||
finally {
|
||||
span.end();
|
||||
}
|
||||
assertThatMdcContainsUnsetTraceId();
|
||||
assertThat(MDC.get(COUNTRY_CODE)).isNullOrEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
private Span createSpan(Tracer tracer) {
|
||||
return tracer.nextSpan().name("span");
|
||||
}
|
||||
|
||||
private Tracer tracer(ApplicationContext context) {
|
||||
return context.getBean(Tracer.class);
|
||||
}
|
||||
|
||||
private void assertThatTracingContextIsInitialized(AutoConfig autoConfig) {
|
||||
if (autoConfig == AutoConfig.OTEL_B3) {
|
||||
assertThat(Context.current()).isEqualTo(Context.root());
|
||||
}
|
||||
}
|
||||
|
||||
private void assertThatMdcContainsUnsetTraceId() {
|
||||
assertThat(isInvalidBraveTraceId() || isInvalidOtelTraceId()).isTrue();
|
||||
}
|
||||
|
||||
private boolean isInvalidBraveTraceId() {
|
||||
return MDC.get("traceId") == null;
|
||||
}
|
||||
|
||||
private boolean isInvalidOtelTraceId() {
|
||||
return MDC.get("traceId").equals("00000000000000000000000000000000");
|
||||
}
|
||||
|
||||
enum AutoConfig implements Supplier<ApplicationContextRunner> {
|
||||
|
||||
BRAVE_W3C {
|
||||
@Override
|
||||
public ApplicationContextRunner get() {
|
||||
return new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(BraveAutoConfiguration.class)).withPropertyValues(
|
||||
"management.tracing.baggage.remote-fields=x-vcap-request-id,country-code,bp",
|
||||
"management.tracing.baggage.correlation.fields=country-code,bp");
|
||||
}
|
||||
},
|
||||
|
||||
OTEL_W3C {
|
||||
@Override
|
||||
public ApplicationContextRunner get() {
|
||||
return new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class))
|
||||
.withPropertyValues(
|
||||
"management.tracing.baggage.remote-fields=x-vcap-request-id,country-code,bp",
|
||||
"management.tracing.baggage.correlation.fields=country-code,bp");
|
||||
}
|
||||
},
|
||||
|
||||
BRAVE_B3 {
|
||||
@Override
|
||||
public ApplicationContextRunner get() {
|
||||
return new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(BraveAutoConfiguration.class))
|
||||
.withPropertyValues("management.tracing.propagation.type=B3",
|
||||
"management.tracing.baggage.remote-fields=x-vcap-request-id,country-code,bp",
|
||||
"management.tracing.baggage.correlation.fields=country-code,bp");
|
||||
}
|
||||
},
|
||||
|
||||
OTEL_B3 {
|
||||
@Override
|
||||
public ApplicationContextRunner get() {
|
||||
return new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class))
|
||||
.withPropertyValues("management.tracing.propagation.type=B3",
|
||||
"management.tracing.baggage.remote-fields=x-vcap-request-id,country-code,bp",
|
||||
"management.tracing.baggage.correlation.fields=country-code,bp");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -18,6 +18,8 @@ package org.springframework.boot.actuate.autoconfigure.tracing;
|
|||
|
||||
import brave.Tracer;
|
||||
import brave.Tracing;
|
||||
import brave.baggage.BaggagePropagation;
|
||||
import brave.baggage.CorrelationScopeConfig.SingleCorrelationField;
|
||||
import brave.http.HttpClientHandler;
|
||||
import brave.http.HttpClientRequest;
|
||||
import brave.http.HttpClientResponse;
|
||||
|
|
@ -26,12 +28,16 @@ import brave.http.HttpServerRequest;
|
|||
import brave.http.HttpServerResponse;
|
||||
import brave.http.HttpTracing;
|
||||
import brave.propagation.CurrentTraceContext;
|
||||
import brave.propagation.CurrentTraceContext.ScopeDecorator;
|
||||
import brave.propagation.Propagation;
|
||||
import brave.propagation.Propagation.Factory;
|
||||
import brave.sampler.Sampler;
|
||||
import io.micrometer.tracing.brave.bridge.BraveBaggageManager;
|
||||
import io.micrometer.tracing.brave.bridge.BraveHttpClientHandler;
|
||||
import io.micrometer.tracing.brave.bridge.BraveHttpServerHandler;
|
||||
import io.micrometer.tracing.brave.bridge.BraveTracer;
|
||||
import io.micrometer.tracing.brave.bridge.W3CPropagation;
|
||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Answers;
|
||||
|
||||
|
|
@ -57,6 +63,7 @@ class BraveAutoConfigurationTests {
|
|||
@Test
|
||||
void shouldSupplyDefaultBeans() {
|
||||
this.contextRunner.run((context) -> {
|
||||
assertThat(context).hasSingleBean(BraveAutoConfiguration.class);
|
||||
assertThat(context).hasSingleBean(Tracing.class);
|
||||
assertThat(context).hasSingleBean(Tracer.class);
|
||||
assertThat(context).hasSingleBean(CurrentTraceContext.class);
|
||||
|
|
@ -66,7 +73,11 @@ class BraveAutoConfigurationTests {
|
|||
assertThat(context).hasSingleBean(HttpServerHandler.class);
|
||||
assertThat(context).hasSingleBean(HttpClientHandler.class);
|
||||
assertThat(context).hasSingleBean(BraveTracer.class);
|
||||
assertThat(context).hasSingleBean(BraveBaggageManager.class);
|
||||
assertThat(context).hasSingleBean(BraveHttpServerHandler.class);
|
||||
assertThat(context).hasSingleBean(BraveHttpClientHandler.class);
|
||||
assertThat(context).hasSingleBean(Propagation.Factory.class);
|
||||
assertThat(context).hasSingleBean(BaggagePropagation.FactoryBuilder.class);
|
||||
assertThat(context).hasSingleBean(BraveTracer.class);
|
||||
assertThat(context).hasSingleBean(BraveHttpServerHandler.class);
|
||||
assertThat(context).hasSingleBean(BraveHttpClientHandler.class);
|
||||
});
|
||||
|
|
@ -99,6 +110,19 @@ class BraveAutoConfigurationTests {
|
|||
assertThat(context).hasSingleBean(BraveHttpServerHandler.class);
|
||||
assertThat(context).hasBean("customBraveHttpClientHandler");
|
||||
assertThat(context).hasSingleBean(BraveHttpClientHandler.class);
|
||||
assertThat(context).hasBean("customHttpServerHandler");
|
||||
assertThat(context).hasSingleBean(HttpServerHandler.class);
|
||||
assertThat(context).hasBean("customHttpClientHandler");
|
||||
assertThat(context).hasSingleBean(HttpClientHandler.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyMicrometerBeans() {
|
||||
this.contextRunner.run((context) -> {
|
||||
assertThat(context).hasSingleBean(BraveTracer.class);
|
||||
assertThat(context).hasSingleBean(BraveHttpServerHandler.class);
|
||||
assertThat(context).hasSingleBean(BraveHttpClientHandler.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -110,16 +134,83 @@ class BraveAutoConfigurationTests {
|
|||
|
||||
@Test
|
||||
void shouldNotSupplyBeansIfMicrometerIsMissing() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader("brave"))
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader("io.micrometer"))
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(BraveAutoConfiguration.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyW3CPropagationFactoryByDefault() {
|
||||
this.contextRunner.run((context) -> {
|
||||
assertThat(context).hasBean("propagationFactory");
|
||||
assertThat(context).hasSingleBean(W3CPropagation.class);
|
||||
assertThat(context).hasSingleBean(BaggagePropagation.FactoryBuilder.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyB3PropagationFactoryViaProperty() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.propagation.type=B3").run((context) -> {
|
||||
assertThat(context).hasBean("propagationFactory");
|
||||
assertThat(context.getBean(Factory.class).toString()).isEqualTo("B3Propagation");
|
||||
assertThat(context).hasSingleBean(BaggagePropagation.FactoryBuilder.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupplyBeansIfTracingIsDisabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.enabled=false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(BraveAutoConfiguration.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupplyCorrelationScopeDecoratorIfBaggageDisabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.baggage.enabled=false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("correlationScopeDecorator"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyW3CWithoutBaggageByDefaultIfBaggageDisabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.baggage.enabled=false")
|
||||
.run((context) -> assertThat(context).hasSingleBean(W3CPropagation.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyB3WithoutBaggageIfBaggageDisabledAndB3Picked() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.baggage.enabled=false",
|
||||
"management.tracing.propagation.type=B3").run((context) -> {
|
||||
assertThat(context).hasBean("propagationFactory");
|
||||
assertThat(context.getBean(Factory.class).toString()).isEqualTo("B3Propagation");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotApplyCorrelationFieldsIfBaggageCorrelationDisabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.baggage.correlation.enabled=false",
|
||||
"management.tracing.baggage.correlation.fields=alpha,bravo").run((context) -> {
|
||||
ScopeDecorator scopeDecorator = context.getBean(ScopeDecorator.class);
|
||||
assertThat(scopeDecorator)
|
||||
.extracting("fields", InstanceOfAssertFactories.array(SingleCorrelationField[].class))
|
||||
.hasSize(2);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotApplyCorrelationFieldsIfBaggageCorrelationEnabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.baggage.correlation.enabled=true",
|
||||
"management.tracing.baggage.correlation.fields=alpha,bravo").run((context) -> {
|
||||
ScopeDecorator scopeDecorator = context.getBean(ScopeDecorator.class);
|
||||
assertThat(scopeDecorator)
|
||||
.extracting("fields", InstanceOfAssertFactories.array(SingleCorrelationField[].class))
|
||||
.hasSize(4);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyMdcCorrelationScopeDecoratorIfBaggageCorrelationDisabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.baggage.correlation.enabled=false")
|
||||
.run((context) -> assertThat(context).hasBean("mdcCorrelationScopeDecoratorBuilder"));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
private static class CustomConfiguration {
|
||||
|
||||
|
|
|
|||
|
|
@ -16,20 +16,29 @@
|
|||
|
||||
package org.springframework.boot.actuate.autoconfigure.tracing;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.micrometer.tracing.otel.bridge.OtelCurrentTraceContext;
|
||||
import io.micrometer.tracing.otel.bridge.OtelHttpClientHandler;
|
||||
import io.micrometer.tracing.otel.bridge.OtelHttpServerHandler;
|
||||
import io.micrometer.tracing.otel.bridge.OtelPropagator;
|
||||
import io.micrometer.tracing.otel.bridge.OtelTracer;
|
||||
import io.micrometer.tracing.otel.bridge.OtelTracer.EventPublisher;
|
||||
import io.micrometer.tracing.otel.bridge.Slf4JBaggageEventListener;
|
||||
import io.micrometer.tracing.otel.bridge.Slf4JEventListener;
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.api.trace.Tracer;
|
||||
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
|
||||
import io.opentelemetry.context.propagation.ContextPropagators;
|
||||
import io.opentelemetry.context.propagation.TextMapPropagator;
|
||||
import io.opentelemetry.extension.trace.propagation.B3Propagator;
|
||||
import io.opentelemetry.sdk.trace.SdkTracerProvider;
|
||||
import io.opentelemetry.sdk.trace.SpanProcessor;
|
||||
import io.opentelemetry.sdk.trace.samplers.Sampler;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.Answers;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
|
|
@ -63,8 +72,12 @@ class OpenTelemetryAutoConfigurationTests {
|
|||
assertThat(context).hasSingleBean(SdkTracerProvider.class);
|
||||
assertThat(context).hasSingleBean(ContextPropagators.class);
|
||||
assertThat(context).hasSingleBean(Sampler.class);
|
||||
assertThat(context).hasSingleBean(SpanProcessor.class);
|
||||
assertThat(context).hasSingleBean(Tracer.class);
|
||||
assertThat(context).hasSingleBean(Slf4JEventListener.class);
|
||||
assertThat(context).hasSingleBean(Slf4JBaggageEventListener.class);
|
||||
assertThat(context).hasSingleBean(SpanProcessor.class);
|
||||
assertThat(context).hasSingleBean(OtelPropagator.class);
|
||||
assertThat(context).hasSingleBean(TextMapPropagator.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -81,8 +94,12 @@ class OpenTelemetryAutoConfigurationTests {
|
|||
assertThat(context).doesNotHaveBean(SdkTracerProvider.class);
|
||||
assertThat(context).doesNotHaveBean(ContextPropagators.class);
|
||||
assertThat(context).doesNotHaveBean(Sampler.class);
|
||||
assertThat(context).doesNotHaveBean(SpanProcessor.class);
|
||||
assertThat(context).doesNotHaveBean(Tracer.class);
|
||||
assertThat(context).doesNotHaveBean(Slf4JEventListener.class);
|
||||
assertThat(context).doesNotHaveBean(Slf4JBaggageEventListener.class);
|
||||
assertThat(context).doesNotHaveBean(SpanProcessor.class);
|
||||
assertThat(context).doesNotHaveBean(OtelPropagator.class);
|
||||
assertThat(context).doesNotHaveBean(TextMapPropagator.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -107,13 +124,84 @@ class OpenTelemetryAutoConfigurationTests {
|
|||
assertThat(context).hasSingleBean(ContextPropagators.class);
|
||||
assertThat(context).hasBean("customSampler");
|
||||
assertThat(context).hasSingleBean(Sampler.class);
|
||||
assertThat(context).hasBean("customSpanProcessor");
|
||||
assertThat(context).hasSingleBean(SpanProcessor.class);
|
||||
assertThat(context).hasBean("customTracer");
|
||||
assertThat(context).hasSingleBean(Tracer.class);
|
||||
assertThat(context).hasBean("customSlf4jEventListener");
|
||||
assertThat(context).hasSingleBean(Slf4JEventListener.class);
|
||||
assertThat(context).hasBean("customSlf4jBaggageEventListener");
|
||||
assertThat(context).hasSingleBean(Slf4JBaggageEventListener.class);
|
||||
assertThat(context).hasBean("customOtelPropagator");
|
||||
assertThat(context).hasSingleBean(OtelPropagator.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAllowMultipleSpanProcessors() {
|
||||
this.contextRunner.withUserConfiguration(CustomConfiguration.class).run((context) -> {
|
||||
assertThat(context.getBeansOfType(SpanProcessor.class)).hasSize(2);
|
||||
assertThat(context).hasBean("customSpanProcessor");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAllowMultipleTextMapPropagators() {
|
||||
this.contextRunner.withUserConfiguration(CustomConfiguration.class).run((context) -> {
|
||||
assertThat(context.getBeansOfType(TextMapPropagator.class)).hasSize(2);
|
||||
assertThat(context).hasBean("customTextMapPropagator");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupplySlf4jBaggageEventListenerBaggageCorrelationDisabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.baggage.correlation.enabled=false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(Slf4JBaggageEventListener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupplySlf4JBaggageEventListenerWhenBaggageDisabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.baggage.enabled=false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(Slf4JBaggageEventListener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyB3PropagationIfPropagationPropertySet() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.propagation.type=B3").run((context) -> {
|
||||
assertThat(context).hasBean("b3BaggageTextMapPropagator");
|
||||
assertThat(context).doesNotHaveBean(W3CTraceContextPropagator.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyB3PropagationIfPropagationPropertySetAndBaggageDisabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.propagation.type=B3",
|
||||
"management.tracing.baggage.enabled=false").run((context) -> {
|
||||
assertThat(context).hasSingleBean(B3Propagator.class);
|
||||
assertThat(context).hasBean("b3TextMapPropagator");
|
||||
assertThat(context).doesNotHaveBean(W3CTraceContextPropagator.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyW3CPropagationWithBaggageByDefault() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasBean("w3cTextMapPropagatorWithBaggage"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyW3CPropagationWithoutBaggageWhenDisabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.baggage.enabled=false")
|
||||
.run((context) -> assertThat(context).hasBean("w3cTextMapPropagatorWithoutBaggage"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplyB3PropagationWithoutBaggageWhenBaggageDisabledAndB3PropagationEnabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.baggage.enabled=false",
|
||||
"management.tracing.propagation.type=B3").run((context) -> {
|
||||
assertThat(context).hasBean("b3TextMapPropagator");
|
||||
assertThat(context).hasSingleBean(B3Propagator.class);
|
||||
assertThat(context).doesNotHaveBean("w3cTextMapPropagatorWithoutBaggage");
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
private static class CustomConfiguration {
|
||||
|
||||
|
|
@ -172,6 +260,56 @@ class OpenTelemetryAutoConfigurationTests {
|
|||
return mock(Tracer.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
Slf4JEventListener customSlf4jEventListener() {
|
||||
return new Slf4JEventListener();
|
||||
}
|
||||
|
||||
@Bean
|
||||
Slf4JBaggageEventListener customSlf4jBaggageEventListener() {
|
||||
return new Slf4JBaggageEventListener(List.of("alpha"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
OtelPropagator customOtelPropagator(ContextPropagators propagators, Tracer tracer) {
|
||||
return new OtelPropagator(propagators, tracer);
|
||||
}
|
||||
|
||||
@Bean
|
||||
TextMapPropagator customTextMapPropagator() {
|
||||
return mock(TextMapPropagator.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
private static class OpenTelemetryConfiguration {
|
||||
|
||||
@Bean
|
||||
OpenTelemetry openTelemetry() {
|
||||
return mock(OpenTelemetry.class, Answers.RETURNS_MOCKS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
private static class ContextPropagatorsConfiguration {
|
||||
|
||||
@Bean
|
||||
ContextPropagators contextPropagators() {
|
||||
return mock(ContextPropagators.class, Answers.RETURNS_MOCKS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
private static class CustomFactoryConfiguration {
|
||||
|
||||
@Bean
|
||||
TextMapPropagator customPropagationFactory() {
|
||||
return mock(TextMapPropagator.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue