Add configuration to put baggage automatically to MDC
with this change it's enough to set a property to automatically propagate a baggage key to MDC fixes gh-1071
This commit is contained in:
@@ -420,6 +420,11 @@ There are two properties to achieve this.
|
||||
With the `spring.sleuth.baggage-keys`, you set keys that get prefixed with `baggage-` for HTTP calls and `baggage_` for messaging.
|
||||
You can also use the `spring.sleuth.propagation-keys` property to pass a list of prefixed keys that are whitelisted without any prefix.
|
||||
|
||||
In order to automatically set the baggage values to Slf4j's MDC, you have to set
|
||||
the `spring.sleuth.log.slf4j.whitelisted-mdc-keys` property with a list of whitelisted
|
||||
baggage keys. E.g. `spring.sleuth.log.slf4j.whitelisted-mdc-keys=foo` will set the value of the
|
||||
`foo` baggage into MDC.
|
||||
|
||||
==== Extracting a Propagated Context
|
||||
|
||||
The `TraceContext.Extractor<C>` reads trace identifiers and sampling status from an incoming request or message.
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.sleuth.autoconfig.SleuthProperties;
|
||||
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -47,8 +48,9 @@ public class SleuthLogAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "spring.sleuth.log.slf4j.enabled", matchIfMissing = true)
|
||||
public CurrentTraceContext.ScopeDecorator slf4jSpanDecorator() {
|
||||
return new Slf4jScopeDecorator();
|
||||
public CurrentTraceContext.ScopeDecorator slf4jSpanDecorator(SleuthProperties sleuthProperties,
|
||||
SleuthSlf4jProperties sleuthSlf4jProperties) {
|
||||
return new Slf4jScopeDecorator(sleuthProperties, sleuthSlf4jProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.cloud.sleuth.log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
@@ -28,10 +31,15 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
public class SleuthSlf4jProperties {
|
||||
|
||||
/**
|
||||
* Enable a {@link Slf4jCurrentTraceContext} that prints tracing information in the logs.
|
||||
* Enable a {@link Slf4jScopeDecorator} that prints tracing information in the logs.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* A list of keys to be put from baggage to MDC
|
||||
*/
|
||||
private List<String> whitelistedMdcKeys = new ArrayList<>();
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
@@ -39,4 +47,12 @@ public class SleuthSlf4jProperties {
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public List<String> getWhitelistedMdcKeys() {
|
||||
return this.whitelistedMdcKeys;
|
||||
}
|
||||
|
||||
public void setWhitelistedMdcKeys(List<String> whitelistedMdcKeys) {
|
||||
this.whitelistedMdcKeys = whitelistedMdcKeys;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,21 @@
|
||||
|
||||
package org.springframework.cloud.sleuth.log;
|
||||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import brave.internal.HexCodec;
|
||||
import brave.internal.Nullable;
|
||||
import brave.propagation.CurrentTraceContext;
|
||||
import brave.propagation.ExtraFieldPropagation;
|
||||
import brave.propagation.TraceContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.cloud.sleuth.autoconfig.SleuthProperties;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Adds {@linkplain MDC} properties "traceId", "parentId", "spanId" and "spanExportable" when a {@link
|
||||
@@ -44,6 +52,14 @@ final class Slf4jScopeDecorator implements CurrentTraceContext.ScopeDecorator {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Slf4jScopeDecorator.class);
|
||||
|
||||
private final SleuthProperties sleuthProperties;
|
||||
private final SleuthSlf4jProperties sleuthSlf4jProperties;
|
||||
|
||||
Slf4jScopeDecorator(SleuthProperties sleuthProperties, SleuthSlf4jProperties sleuthSlf4jProperties) {
|
||||
this.sleuthProperties = sleuthProperties;
|
||||
this.sleuthSlf4jProperties = sleuthSlf4jProperties;
|
||||
}
|
||||
|
||||
@Override public CurrentTraceContext.Scope decorateScope(TraceContext currentSpan,
|
||||
CurrentTraceContext.Scope scope) {
|
||||
final String previousTraceId = MDC.get("traceId");
|
||||
@@ -54,6 +70,10 @@ final class Slf4jScopeDecorator implements CurrentTraceContext.ScopeDecorator {
|
||||
final String legacyPreviousParentId = MDC.get(LEGACY_PARENT_ID_NAME);
|
||||
final String legacyPreviousSpanId = MDC.get(LEGACY_SPAN_ID_NAME);
|
||||
final String legacySpanExportable = MDC.get(LEGACY_EXPORTABLE_NAME);
|
||||
final List<AbstractMap.SimpleEntry<String, String>> previousMdc =
|
||||
whitelistedBaggageKeys(currentSpan)
|
||||
.map(s -> new AbstractMap.SimpleEntry<>(s, MDC.get(s)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (currentSpan != null) {
|
||||
String traceIdString = currentSpan.traceIdString();
|
||||
@@ -76,6 +96,8 @@ final class Slf4jScopeDecorator implements CurrentTraceContext.ScopeDecorator {
|
||||
log.trace("With parent: {}", currentSpan.parentId());
|
||||
}
|
||||
}
|
||||
whitelistedBaggageKeys(currentSpan)
|
||||
.forEach(s -> MDC.put(s, ExtraFieldPropagation.get(currentSpan, s)));
|
||||
}
|
||||
else {
|
||||
MDC.remove("traceId");
|
||||
@@ -86,6 +108,7 @@ final class Slf4jScopeDecorator implements CurrentTraceContext.ScopeDecorator {
|
||||
MDC.remove(LEGACY_PARENT_ID_NAME);
|
||||
MDC.remove(LEGACY_SPAN_ID_NAME);
|
||||
MDC.remove(LEGACY_EXPORTABLE_NAME);
|
||||
whitelistedBaggageKeys(currentSpan).forEach(MDC::remove);
|
||||
}
|
||||
|
||||
class ThreadContextCurrentTraceContextScope implements CurrentTraceContext.Scope {
|
||||
@@ -100,11 +123,18 @@ final class Slf4jScopeDecorator implements CurrentTraceContext.ScopeDecorator {
|
||||
replace(LEGACY_PARENT_ID_NAME, legacyPreviousParentId);
|
||||
replace(LEGACY_SPAN_ID_NAME, legacyPreviousSpanId);
|
||||
replace(LEGACY_EXPORTABLE_NAME, legacySpanExportable);
|
||||
previousMdc.forEach(e -> replace(e.getKey(), e.getValue()));
|
||||
}
|
||||
}
|
||||
return new ThreadContextCurrentTraceContextScope();
|
||||
}
|
||||
|
||||
private Stream<String> whitelistedBaggageKeys(TraceContext context) {
|
||||
return this.sleuthProperties.getBaggageKeys().stream()
|
||||
.filter(s -> this.sleuthSlf4jProperties.getWhitelistedMdcKeys().contains(s) &&
|
||||
context != null && StringUtils.hasText(ExtraFieldPropagation.get(context, s)));
|
||||
}
|
||||
|
||||
private void log(String text, TraceContext span) {
|
||||
if (span == null) {
|
||||
return;
|
||||
|
||||
@@ -17,43 +17,53 @@
|
||||
package org.springframework.cloud.sleuth.log;
|
||||
|
||||
import brave.Span;
|
||||
import brave.Tracing;
|
||||
import brave.Tracer;
|
||||
import brave.propagation.CurrentTraceContext.Scope;
|
||||
import brave.propagation.StrictCurrentTraceContext;
|
||||
import brave.propagation.ExtraFieldPropagation;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE,
|
||||
properties = {
|
||||
"spring.sleuth.baggage-keys=my-baggage",
|
||||
"spring.sleuth.log.slf4j.whitelisted-mdc-keys=my-baggage"
|
||||
})
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
public class Slf4JSpanLoggerTest {
|
||||
|
||||
ArrayListSpanReporter reporter = new ArrayListSpanReporter();
|
||||
Tracing tracing = Tracing.newBuilder()
|
||||
.currentTraceContext(new StrictCurrentTraceContext())
|
||||
.spanReporter(this.reporter)
|
||||
.build();
|
||||
|
||||
Span span = this.tracing.tracer().nextSpan().name("span").start();
|
||||
Slf4jScopeDecorator slf4jScopeDecorator = new Slf4jScopeDecorator();
|
||||
@Autowired Tracer tracer;
|
||||
@Autowired Slf4jScopeDecorator slf4jScopeDecorator;
|
||||
|
||||
Span span;
|
||||
|
||||
@Before
|
||||
@After
|
||||
public void setup() {
|
||||
MDC.clear();
|
||||
this.span = this.tracer.nextSpan().name("span").start();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_set_entries_to_mdc_from_span() throws Exception {
|
||||
Scope scope = this.slf4jScopeDecorator.decorateScope(this.span.context(), () -> { });
|
||||
|
||||
assertThat(MDC.get("X-B3-TraceId")).isEqualTo(span.context().traceIdString());
|
||||
assertThat(MDC.get("traceId")).isEqualTo(span.context().traceIdString());
|
||||
assertThat(MDC.get("X-B3-TraceId")).isEqualTo(this.span.context().traceIdString());
|
||||
assertThat(MDC.get("traceId")).isEqualTo(this.span.context().traceIdString());
|
||||
|
||||
scope.close();
|
||||
|
||||
@@ -61,6 +71,18 @@ public class Slf4JSpanLoggerTest {
|
||||
assertThat(MDC.get("traceId")).isNullOrEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_set_entries_to_mdc_from_span_with_baggage() throws Exception {
|
||||
ExtraFieldPropagation.set(this.span.context(), "my-baggage", "my-value");
|
||||
Scope scope = this.slf4jScopeDecorator.decorateScope(this.span.context(), () -> { });
|
||||
|
||||
assertThat(MDC.get("my-baggage")).isEqualTo("my-value");
|
||||
|
||||
scope.close();
|
||||
|
||||
assertThat(MDC.get("my-baggage")).isNullOrEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_remove_entries_from_mdc_from_null_span() throws Exception {
|
||||
MDC.put("X-B3-TraceId", "A");
|
||||
|
||||
Reference in New Issue
Block a user