mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-05 00:56:58 +08:00
Add local and tagged correlation fields
Local fields only work in Brave and not with OpenTelemetry. Tagged fields work both with Brave and with OpenTelemetry. See gh-37435
This commit is contained in:
parent
91d187ca38
commit
0ca55bf0a6
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.Collection;
|
||||
|
||||
import brave.Tags;
|
||||
import brave.baggage.BaggageField;
|
||||
import brave.handler.MutableSpan;
|
||||
import brave.handler.SpanHandler;
|
||||
import brave.propagation.TraceContext;
|
||||
|
||||
class BaggageTagSpanHandler extends SpanHandler {
|
||||
|
||||
private final Collection<BaggageField> fieldsToTag;
|
||||
|
||||
BaggageTagSpanHandler(Collection<BaggageField> fieldsToTag) {
|
||||
this.fieldsToTag = fieldsToTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean end(TraceContext context, MutableSpan span, Cause cause) {
|
||||
for (BaggageField field : this.fieldsToTag) {
|
||||
Tags.BAGGAGE_FIELD.tag(field, context, span);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@ -27,6 +27,7 @@ import brave.baggage.CorrelationScopeConfig.SingleCorrelationField;
|
||||
import brave.baggage.CorrelationScopeCustomizer;
|
||||
import brave.baggage.CorrelationScopeDecorator;
|
||||
import brave.context.slf4j.MDCScopeDecorator;
|
||||
import brave.handler.SpanHandler;
|
||||
import brave.propagation.CurrentTraceContext.ScopeDecorator;
|
||||
import brave.propagation.Propagation;
|
||||
import brave.propagation.Propagation.Factory;
|
||||
@ -40,6 +41,7 @@ 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.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Brave propagation configurations. They are imported by {@link BraveAutoConfiguration}.
|
||||
@ -120,6 +122,27 @@ class BravePropagationConfigurations {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(1)
|
||||
BaggagePropagationCustomizer localFieldsBaggagePropagationCustomizer() {
|
||||
return (builder) -> {
|
||||
List<String> localFields = this.tracingProperties.getBaggage().getLocalFields();
|
||||
for (String localFieldName : localFields) {
|
||||
builder.add(BaggagePropagationConfig.SingleBaggageField.local(BaggageField.create(localFieldName)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(2)
|
||||
SpanHandler baggageTagSpanHandler() {
|
||||
List<String> tagFields = this.tracingProperties.getBaggage().getTagFields();
|
||||
if (CollectionUtils.isEmpty(tagFields)) {
|
||||
return SpanHandler.NOOP;
|
||||
}
|
||||
return new BaggageTagSpanHandler(tagFields.stream().map(BaggageField::create).toList());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnEnabledTracing
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.tracing;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import io.micrometer.tracing.SpanCustomizer;
|
||||
@ -47,6 +46,8 @@ import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
|
||||
import io.opentelemetry.sdk.trace.export.BatchSpanProcessorBuilder;
|
||||
import io.opentelemetry.sdk.trace.export.SpanExporter;
|
||||
import io.opentelemetry.sdk.trace.samplers.Sampler;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.SpringBootVersion;
|
||||
@ -57,6 +58,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for OpenTelemetry tracing.
|
||||
@ -75,10 +77,15 @@ import org.springframework.context.annotation.Import;
|
||||
OpenTelemetryPropagationConfigurations.NoPropagation.class })
|
||||
public class OpenTelemetryAutoConfiguration {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(OpenTelemetryAutoConfiguration.class);
|
||||
|
||||
private final TracingProperties tracingProperties;
|
||||
|
||||
OpenTelemetryAutoConfiguration(TracingProperties tracingProperties) {
|
||||
this.tracingProperties = tracingProperties;
|
||||
if (!CollectionUtils.isEmpty(this.tracingProperties.getBaggage().getLocalFields())) {
|
||||
logger.warn("Local fields are not supported when using OpenTelemetry!");
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ -137,9 +144,10 @@ public class OpenTelemetryAutoConfiguration {
|
||||
@ConditionalOnMissingBean(io.micrometer.tracing.Tracer.class)
|
||||
OtelTracer micrometerOtelTracer(Tracer tracer, EventPublisher eventPublisher,
|
||||
OtelCurrentTraceContext otelCurrentTraceContext) {
|
||||
List<String> remoteFields = this.tracingProperties.getBaggage().getRemoteFields();
|
||||
List<String> tagFields = this.tracingProperties.getBaggage().getTagFields();
|
||||
return new OtelTracer(tracer, otelCurrentTraceContext, eventPublisher,
|
||||
new OtelBaggageManager(otelCurrentTraceContext, this.tracingProperties.getBaggage().getRemoteFields(),
|
||||
Collections.emptyList()));
|
||||
new OtelBaggageManager(otelCurrentTraceContext, remoteFields, tagFields));
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.tracing;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import io.micrometer.tracing.otel.bridge.OtelBaggageManager;
|
||||
@ -73,8 +72,9 @@ class OpenTelemetryPropagationConfigurations {
|
||||
@ConditionalOnEnabledTracing
|
||||
TextMapPropagator textMapPropagatorWithBaggage(OtelCurrentTraceContext otelCurrentTraceContext) {
|
||||
List<String> remoteFields = this.tracingProperties.getBaggage().getRemoteFields();
|
||||
List<String> tagFields = this.tracingProperties.getBaggage().getTagFields();
|
||||
BaggageTextMapPropagator baggagePropagator = new BaggageTextMapPropagator(remoteFields,
|
||||
new OtelBaggageManager(otelCurrentTraceContext, remoteFields, Collections.emptyList()));
|
||||
new OtelBaggageManager(otelCurrentTraceContext, remoteFields, tagFields));
|
||||
return CompositeTextMapPropagator.create(this.tracingProperties.getPropagation(), baggagePropagator);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@ -103,6 +103,17 @@ public class TracingProperties {
|
||||
*/
|
||||
private List<String> remoteFields = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* List of fields that should be accessible within the JVM process but not
|
||||
* propagated over the wire. Local fields are not supported with OpenTelemetry.
|
||||
*/
|
||||
private List<String> localFields = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* List of fields that should automatically become tags.
|
||||
*/
|
||||
private List<String> tagFields = new ArrayList<>();
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
@ -123,10 +134,26 @@ public class TracingProperties {
|
||||
return this.remoteFields;
|
||||
}
|
||||
|
||||
public List<String> getLocalFields() {
|
||||
return this.localFields;
|
||||
}
|
||||
|
||||
public List<String> getTagFields() {
|
||||
return this.tagFields;
|
||||
}
|
||||
|
||||
public void setRemoteFields(List<String> remoteFields) {
|
||||
this.remoteFields = remoteFields;
|
||||
}
|
||||
|
||||
public void setLocalFields(List<String> localFields) {
|
||||
this.localFields = localFields;
|
||||
}
|
||||
|
||||
public void setTagFields(List<String> tagFields) {
|
||||
this.tagFields = tagFields;
|
||||
}
|
||||
|
||||
public static class Correlation {
|
||||
|
||||
/**
|
||||
|
@ -227,6 +227,16 @@ class BaggagePropagationIntegrationTests {
|
||||
"management.tracing.baggage.remote-fields=x-vcap-request-id,country-code,bp",
|
||||
"management.tracing.baggage.correlation.fields=country-code,bp");
|
||||
}
|
||||
},
|
||||
|
||||
BRAVE_LOCAL_FIELDS {
|
||||
@Override
|
||||
public ApplicationContextRunner get() {
|
||||
return new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(BraveAutoConfiguration.class))
|
||||
.withPropertyValues("management.tracing.baggage.local-fields=country-code,bp",
|
||||
"management.tracing.baggage.correlation.fields=country-code,bp");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import brave.Span;
|
||||
import brave.SpanCustomizer;
|
||||
import brave.Tracer;
|
||||
import brave.Tracing;
|
||||
import brave.baggage.BaggageField;
|
||||
import brave.baggage.BaggagePropagation;
|
||||
import brave.baggage.CorrelationScopeConfig.SingleCorrelationField;
|
||||
import brave.handler.SpanHandler;
|
||||
@ -344,6 +345,22 @@ class BraveAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateTagHandler() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.baggage.tag-fields=country-code,bp")
|
||||
.run((context) -> assertThat(context.getBean(BaggageTagSpanHandler.class)).extracting("fieldsToTag")
|
||||
.asInstanceOf(InstanceOfAssertFactories.list(BaggageField.class))
|
||||
.extracting(BaggageField::name)
|
||||
.containsExactlyInAnyOrder("country-code", "bp"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void noopOnNoTagFields() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.baggage.tag-fields=")
|
||||
.run((context) -> assertThat(context.getBean("baggageTagSpanHandler", SpanHandler.class))
|
||||
.isSameAs(SpanHandler.NOOP));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDisablePropagationIfTracingIsDisabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.enabled=false").run((context) -> {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@ -51,6 +51,7 @@ import io.opentelemetry.sdk.trace.data.SpanData;
|
||||
import io.opentelemetry.sdk.trace.export.SpanExporter;
|
||||
import io.opentelemetry.sdk.trace.samplers.Sampler;
|
||||
import io.opentelemetry.semconv.ResourceAttributes;
|
||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
@ -272,6 +273,22 @@ class OpenTelemetryAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldConfigureRemoteAndTaggedFields() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.tracing.baggage.remote-fields=r1",
|
||||
"management.tracing.baggage.tag-fields=t1")
|
||||
.run((context) -> {
|
||||
CompositeTextMapPropagator propagator = context.getBean(CompositeTextMapPropagator.class);
|
||||
assertThat(propagator).extracting("baggagePropagator.baggageManager.remoteFields")
|
||||
.asInstanceOf(InstanceOfAssertFactories.list(String.class))
|
||||
.containsExactly("r1");
|
||||
assertThat(propagator).extracting("baggagePropagator.baggageManager.tagFields")
|
||||
.asInstanceOf(InstanceOfAssertFactories.list(String.class))
|
||||
.containsExactly("t1");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCustomizeSdkTracerProvider() {
|
||||
this.contextRunner.withUserConfiguration(SdkTracerProviderCustomizationConfiguration.class).run((context) -> {
|
||||
|
Loading…
Reference in New Issue
Block a user