Merge branch '2.2.x'

This commit is contained in:
Adrian Cole
2020-04-03 20:20:58 +08:00
5 changed files with 90 additions and 193 deletions

View File

@@ -33,7 +33,7 @@
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<spring-boot.version>2.3.0.BUILD-SNAPSHOT</spring-boot.version>
<brave.version>5.11.0</brave.version>
<brave.version>5.11.1</brave.version>
<okhttp.version>3.14.6</okhttp.version>
</properties>

View File

@@ -250,7 +250,7 @@
<spring-cloud-stream.version>Horsham.BUILD-SNAPSHOT</spring-cloud-stream.version>
<spring-cloud-netflix.version>3.0.0.BUILD-SNAPSHOT</spring-cloud-netflix.version>
<spring-cloud-openfeign.version>3.0.0.BUILD-SNAPSHOT</spring-cloud-openfeign.version>
<brave.version>5.11.0</brave.version>
<brave.version>5.11.1</brave.version>
<spring-security-boot-autoconfigure.version>2.1.7.RELEASE</spring-security-boot-autoconfigure.version>
<disable.nohttp.checks>false</disable.nohttp.checks>
<okhttp.version>3.14.6</okhttp.version>

View File

@@ -16,22 +16,21 @@
package org.springframework.cloud.sleuth.log;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
import brave.internal.HexCodec;
import brave.internal.Nullable;
import brave.propagation.CurrentTraceContext;
import brave.propagation.ExtraFieldPropagation;
import brave.baggage.BaggageField;
import brave.baggage.BaggageFields;
import brave.baggage.CorrelationField;
import brave.baggage.CorrelationScopeDecorator;
import brave.context.slf4j.MDCScopeDecorator;
import brave.propagation.CurrentTraceContext.Scope;
import brave.propagation.CurrentTraceContext.ScopeDecorator;
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"
@@ -43,171 +42,56 @@ import org.springframework.util.StringUtils;
* @author Marcin Grzejszczak
* @since 2.1.0
*/
final class Slf4jScopeDecorator implements CurrentTraceContext.ScopeDecorator {
final class Slf4jScopeDecorator implements ScopeDecorator {
// Backward compatibility for all logging patterns
private static final ScopeDecorator LEGACY_IDS = MDCScopeDecorator.newBuilder()
.clear()
.addField(CorrelationField.newBuilder(BaggageFields.TRACE_ID)
.name("X-B3-TraceId").build())
.addField(CorrelationField.newBuilder(BaggageFields.PARENT_ID)
.name("X-B3-ParentSpanId").build())
.addField(CorrelationField.newBuilder(BaggageFields.SPAN_ID)
.name("X-B3-SpanId").build())
.addField(CorrelationField.newBuilder(BaggageFields.SAMPLED)
.name("X-Span-Export").build())
.build();
private static final Logger log = LoggerFactory.getLogger(Slf4jScopeDecorator.class);
private final SleuthProperties sleuthProperties;
private final SleuthSlf4jProperties sleuthSlf4jProperties;
private final ScopeDecorator delegate;
Slf4jScopeDecorator(SleuthProperties sleuthProperties,
SleuthSlf4jProperties sleuthSlf4jProperties) {
this.sleuthProperties = sleuthProperties;
this.sleuthSlf4jProperties = sleuthSlf4jProperties;
}
static void replace(String key, @Nullable String value) {
if (value != null) {
MDC.put(key, value);
}
else {
MDC.remove(key);
CorrelationScopeDecorator.Builder builder = MDCScopeDecorator.newBuilder().clear()
.addField(CorrelationField.create(BaggageFields.TRACE_ID))
.addField(CorrelationField.create(BaggageFields.PARENT_ID))
.addField(CorrelationField.create(BaggageFields.SPAN_ID))
.addField(CorrelationField.newBuilder(BaggageFields.SAMPLED)
.name("spanExportable").build());
Set<String> whitelist = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
whitelist.addAll(sleuthSlf4jProperties.getWhitelistedMdcKeys());
// Note: we are adding all the keys as-is because correlation context doesn't
// prefix, only ExtraFieldPropagation does
Set<String> retained = new LinkedHashSet<>();
retained.addAll(sleuthProperties.getBaggageKeys());
retained.addAll(sleuthProperties.getLocalKeys());
retained.addAll(sleuthProperties.getPropagationKeys());
retained.retainAll(whitelist);
// For backwards compatibility set all fields dirty, so that any changes made by
// MDC directly are reverted.
for (String name : retained) {
builder.addField(CorrelationField.newBuilder(BaggageField.create(name))
.dirty().build());
}
this.delegate = builder.build();
}
@Override
public CurrentTraceContext.Scope decorateScope(TraceContext currentSpan,
CurrentTraceContext.Scope scope) {
final String previousTraceId = MDC.get("traceId");
final String previousParentId = MDC.get("parentId");
final String previousSpanId = MDC.get("spanId");
final String spanExportable = MDC.get("spanExportable");
final List<AbstractMap.SimpleEntry<String, String>> previousMdc = previousMdc();
if (currentSpan != null) {
String traceIdString = currentSpan.traceIdString();
MDC.put("traceId", traceIdString);
String parentId = currentSpan.parentId() != null
? HexCodec.toLowerHex(currentSpan.parentId()) : null;
replace("parentId", parentId);
String spanId = HexCodec.toLowerHex(currentSpan.spanId());
MDC.put("spanId", spanId);
String sampled = String.valueOf(currentSpan.sampled());
MDC.put("spanExportable", sampled);
log("Starting scope for span: {}", currentSpan);
if (currentSpan.parentId() != null) {
if (log.isTraceEnabled()) {
log.trace("With parent: {}", currentSpan.parentId());
}
}
for (String key : whitelistedBaggageKeysWithValue(currentSpan)) {
MDC.put(key, ExtraFieldPropagation.get(currentSpan, key));
}
for (String key : whitelistedPropagationKeysWithValue(currentSpan)) {
MDC.put(key, ExtraFieldPropagation.get(currentSpan, key));
}
for (String key : whitelistedLocalKeysWithValue(currentSpan)) {
MDC.put(key, ExtraFieldPropagation.get(currentSpan, key));
}
}
else {
MDC.remove("traceId");
MDC.remove("parentId");
MDC.remove("spanId");
MDC.remove("spanExportable");
for (String s : whitelistedBaggageKeys()) {
MDC.remove(s);
}
for (String s : whitelistedPropagationKeys()) {
MDC.remove(s);
}
for (String s : whitelistedLocalKeys()) {
MDC.remove(s);
}
previousMdc.clear();
}
/**
* Thread context scope.
*
* @author Adrian Cole
*/
class ThreadContextCurrentTraceContextScope implements CurrentTraceContext.Scope {
@Override
public void close() {
log("Closing scope for span: {}", currentSpan);
scope.close();
replace("traceId", previousTraceId);
replace("parentId", previousParentId);
replace("spanId", previousSpanId);
replace("spanExportable", spanExportable);
for (AbstractMap.SimpleEntry<String, String> entry : previousMdc) {
replace(entry.getKey(), entry.getValue());
}
}
}
return new ThreadContextCurrentTraceContextScope();
}
private List<AbstractMap.SimpleEntry<String, String>> previousMdc() {
List<AbstractMap.SimpleEntry<String, String>> previousMdc = new ArrayList<>();
List<String> keys = new ArrayList<>(whitelistedBaggageKeys());
keys.addAll(whitelistedPropagationKeys());
keys.addAll(whitelistedLocalKeys());
for (String key : keys) {
previousMdc.add(new AbstractMap.SimpleEntry<>(key, MDC.get(key)));
}
return previousMdc;
}
private List<String> whitelistedKeys(List<String> keysToFilter) {
List<String> keys = new ArrayList<>();
for (String baggageKey : keysToFilter) {
if (this.sleuthSlf4jProperties.getWhitelistedMdcKeys().contains(baggageKey)) {
keys.add(baggageKey);
}
}
return keys;
}
private List<String> whitelistedBaggageKeys() {
return whitelistedKeys(this.sleuthProperties.getBaggageKeys());
}
private List<String> whitelistedKeysWithValue(TraceContext context,
List<String> keys) {
if (context == null) {
return Collections.EMPTY_LIST;
}
List<String> nonEmpty = new ArrayList<>();
for (String key : keys) {
if (StringUtils.hasText(ExtraFieldPropagation.get(context, key))) {
nonEmpty.add(key);
}
}
return nonEmpty;
}
private List<String> whitelistedBaggageKeysWithValue(TraceContext context) {
return whitelistedKeysWithValue(context, whitelistedBaggageKeys());
}
private List<String> whitelistedPropagationKeys() {
return whitelistedKeys(this.sleuthProperties.getPropagationKeys());
}
private List<String> whitelistedLocalKeys() {
return whitelistedKeys(this.sleuthProperties.getLocalKeys());
}
private List<String> whitelistedPropagationKeysWithValue(TraceContext context) {
return whitelistedKeysWithValue(context, whitelistedPropagationKeys());
}
private List<String> whitelistedLocalKeysWithValue(TraceContext context) {
return whitelistedKeysWithValue(context, whitelistedLocalKeys());
}
private void log(String text, TraceContext span) {
if (span == null) {
return;
}
if (log.isTraceEnabled()) {
log.trace(text, span);
}
public Scope decorateScope(TraceContext context, Scope scope) {
return LEGACY_IDS.decorateScope(context, delegate.decorateScope(context, scope));
}
}

View File

@@ -18,8 +18,10 @@ package org.springframework.cloud.sleuth.log;
import brave.Span;
import brave.Tracer;
import brave.baggage.CorrelationField;
import brave.propagation.CurrentTraceContext.Scope;
import brave.propagation.ExtraFieldPropagation;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -30,13 +32,14 @@ import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import static brave.propagation.CurrentTraceContext.Scope.NOOP;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Marcin Grzejszczak
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = {
"spring.sleuth.baggage-keys=my-baggage",
"spring.sleuth.baggage-keys=my-baggage,my-baggage-two",
"spring.sleuth.propagation-keys=my-propagation",
"spring.sleuth.local-keys=my-local",
"spring.sleuth.log.slf4j.whitelisted-mdc-keys=my-baggage,my-propagation,my-local" })
@@ -96,19 +99,17 @@ public class Slf4JSpanLoggerTest {
ExtraFieldPropagation.set(this.span.context(), "my-baggage", "my-value");
ExtraFieldPropagation.set(this.span.context(), "my-propagation",
"my-propagation-value");
this.slf4jScopeDecorator.decorateScope(this.span.context(), () -> {
});
assertThat(MDC.get("my-baggage")).isEqualTo("my-value");
assertThat(MDC.get("my-propagation")).isEqualTo("my-propagation-value");
try (Scope scope1 = this.slf4jScopeDecorator.decorateScope(this.span.context(),
NOOP)) {
assertThat(MDC.get("my-baggage")).isEqualTo("my-value");
assertThat(MDC.get("my-propagation")).isEqualTo("my-propagation-value");
Scope scope = this.slf4jScopeDecorator.decorateScope(null, () -> {
});
scope.close();
assertThat(MDC.get("my-baggage")).isNullOrEmpty();
assertThat(MDC.get("my-propagation")).isNullOrEmpty();
try (Scope scope2 = this.slf4jScopeDecorator.decorateScope(null, NOOP)) {
assertThat(MDC.get("my-baggage")).isNullOrEmpty();
assertThat(MDC.get("my-propagation")).isNullOrEmpty();
}
}
}
@Test
@@ -117,19 +118,23 @@ public class Slf4JSpanLoggerTest {
MDC.put("my-baggage", "my-value");
MDC.put("my-propagation", "my-propagation-value");
this.slf4jScopeDecorator.decorateScope(this.span.context(), () -> {
});
// the span is holding no baggage so it clears the preceding values
try (Scope scope = this.slf4jScopeDecorator.decorateScope(this.span.context(),
NOOP)) {
assertThat(MDC.get("my-baggage")).isNullOrEmpty();
assertThat(MDC.get("my-propagation")).isNullOrEmpty();
}
assertThat(MDC.get("my-baggage")).isEqualTo("my-value");
assertThat(MDC.get("my-propagation")).isEqualTo("my-propagation-value");
Scope scope = this.slf4jScopeDecorator.decorateScope(null, () -> {
});
try (Scope scope = this.slf4jScopeDecorator.decorateScope(null, NOOP)) {
assertThat(MDC.get("my-baggage")).isNullOrEmpty();
assertThat(MDC.get("my-propagation")).isNullOrEmpty();
}
scope.close();
assertThat(MDC.get("my-baggage")).isNullOrEmpty();
assertThat(MDC.get("my-propagation")).isNullOrEmpty();
assertThat(MDC.get("my-baggage")).isEqualTo("my-value");
assertThat(MDC.get("my-propagation")).isEqualTo("my-propagation-value");
}
@Test
@@ -167,8 +172,16 @@ public class Slf4JSpanLoggerTest {
}
@Test
public void should_pick_previous_mdc_entries_when_their_keys_are_whitelisted()
throws Exception {
public void should_only_include_whitelist() {
assertThat(this.slf4jScopeDecorator).extracting("delegate.fields")
.asInstanceOf(InstanceOfAssertFactories.array(CorrelationField[].class))
.extracting(CorrelationField::name).containsExactly("traceId", "parentId",
"spanId", "spanExportable", "my-baggage", "my-local",
"my-propagation"); // my-baggage-two is baggage not in the whitelist
}
@Test
public void should_pick_previous_mdc_entries_when_their_keys_are_whitelisted() {
MDC.put("my-baggage", "A1");
MDC.put("my-propagation", "B1");

View File

@@ -31,8 +31,8 @@
<name>spring-cloud-sleuth-dependencies</name>
<description>Spring Cloud Sleuth Dependencies</description>
<properties>
<brave.version>5.11.0</brave.version>
<brave.opentracing.version>0.36.0</brave.opentracing.version>
<brave.version>5.11.1</brave.version>
<brave.opentracing.version>0.36.1</brave.opentracing.version>
<grpc.spring.boot.version>3.4.1</grpc.spring.boot.version>
</properties>
<dependencyManagement>