Merge branch '3.0.x' into main

This commit is contained in:
Marcin Grzejszczak
2021-07-28 20:25:10 +02:00
5 changed files with 108 additions and 28 deletions

View File

@@ -18,6 +18,8 @@ package org.springframework.cloud.sleuth;
import java.util.Map;
import org.springframework.lang.Nullable;
/**
* Manages {@link BaggageInScope} entries. Upon retrieval / creation of a baggage entry
* puts it in scope. Scope must be closed.
@@ -38,6 +40,7 @@ public interface BaggageManager {
* @param name baggage name
* @return baggage or {@code null} if not present
*/
@Nullable
BaggageInScope getBaggage(String name);
/**
@@ -46,6 +49,7 @@ public interface BaggageManager {
* @param name baggage name
* @return baggage or {@code null} if not present
*/
@Nullable
BaggageInScope getBaggage(TraceContext traceContext, String name);
/**

View File

@@ -47,7 +47,11 @@ public class BraveBaggageManager implements Closeable, BaggageManager {
@Override
public BaggageInScope getBaggage(TraceContext traceContext, String name) {
return new BraveBaggageInScope(BaggageField.getByName(BraveTraceContext.toBrave(traceContext), name));
BaggageField baggageField = BaggageField.getByName(BraveTraceContext.toBrave(traceContext), name);
if (baggageField == null) {
return null;
}
return new BraveBaggageInScope(baggageField);
}
@Override

View File

@@ -28,6 +28,8 @@ import java.util.Set;
import java.util.stream.Collectors;
import brave.baggage.BaggageField;
import brave.baggage.BaggagePropagation;
import brave.baggage.BaggagePropagationConfig;
import brave.internal.baggage.BaggageFields;
import brave.internal.propagation.StringPropagationAdapter;
import brave.propagation.Propagation;
@@ -38,6 +40,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.sleuth.BaggageInScope;
import org.springframework.cloud.sleuth.internal.EncodingUtils;
import org.springframework.util.StringUtils;
import static java.util.Collections.singletonList;
@@ -118,8 +121,11 @@ class W3CPropagation extends Propagation.Factory implements Propagation<String>
private final W3CBaggagePropagator baggagePropagator;
private final BraveBaggageManager braveBaggageManager;
W3CPropagation(BraveBaggageManager braveBaggageManager, List<String> localFields) {
this.baggagePropagator = new W3CBaggagePropagator(braveBaggageManager, localFields);
this.braveBaggageManager = braveBaggageManager;
}
@Override
@@ -153,11 +159,25 @@ class W3CPropagation extends Propagation.Factory implements Propagation<String>
chars[TRACE_OPTION_OFFSET - 1] = TRACEPARENT_DELIMITER;
copyTraceFlagsHexTo(chars, TRACE_OPTION_OFFSET, context);
setter.put(carrier, TRACE_PARENT, new String(chars, 0, TRACEPARENT_HEADER_SIZE));
// Add baggage
addTraceState(setter, context, carrier);
this.baggagePropagator.injector(setter).inject(context, carrier);
};
}
private <R> void addTraceState(Setter<R, String> setter, TraceContext context, R carrier) {
if (carrier != null) {
BaggageInScope baggage = this.braveBaggageManager.getBaggage(BraveTraceContext.fromBrave(context),
TRACE_STATE);
if (baggage == null) {
return;
}
String traceState = baggage.get(BraveTraceContext.fromBrave(context));
if (StringUtils.hasText(traceState)) {
setter.put(carrier, TRACE_STATE, traceState);
}
}
}
private String padLeftWithZeros(String string, int length) {
if (string.length() >= length) {
return string;
@@ -203,14 +223,15 @@ class W3CPropagation extends Propagation.Factory implements Propagation<String>
}
TraceContextOrSamplingFlags context(TraceContext contextFromParentHeader, String traceStateHeader) {
if (traceStateHeader == null || traceStateHeader.isEmpty()) {
if (!StringUtils.hasText(traceStateHeader)) {
return TraceContextOrSamplingFlags.create(contextFromParentHeader);
}
try {
return TraceContextOrSamplingFlags
.create(TraceContext.newBuilder().traceId(contextFromParentHeader.traceId())
.newBuilder(TraceContext.newBuilder().traceId(contextFromParentHeader.traceId())
.traceIdHigh(contextFromParentHeader.traceIdHigh()).spanId(contextFromParentHeader.spanId())
.sampled(contextFromParentHeader.sampled()).shared(true).build());
.sampled(contextFromParentHeader.sampled()).shared(true).build())
.build();
}
catch (IllegalArgumentException e) {
logger.info("Unparseable tracestate header. Returning span context without state.");
@@ -280,6 +301,10 @@ class W3CBaggagePropagator {
private static final Log log = LogFactory.getLog(W3CBaggagePropagator.class);
private static final String TRACE_STATE = "tracestate";
private static final BaggageField TRACE_STATE_BAGGAGE = BaggageField.create(TRACE_STATE);
private static final String FIELD = "baggage";
private static final List<String> FIELDS = singletonList(FIELD);
@@ -293,6 +318,15 @@ class W3CBaggagePropagator {
this.localFields = localFields;
}
private BaggagePropagation.FactoryBuilder factory() {
return BaggagePropagation.newFactoryBuilder(new Propagation.Factory() {
@Override
public <K> Propagation<K> create(Propagation.KeyFactory<K> keyFactory) {
return null;
}
});
}
public List<String> keys() {
return FIELDS;
}
@@ -308,6 +342,9 @@ class W3CBaggagePropagator {
String[] strings = this.localFields.toArray(new String[0]);
Map<String, String> filtered = extra.toMapFilteringFieldNames(strings);
for (Map.Entry<String, String> entry : filtered.entrySet()) {
if (TRACE_STATE.equalsIgnoreCase(entry.getKey())) {
continue;
}
headerContent.append(entry.getKey()).append("=").append(entry.getValue());
// TODO: [OTEL] No metadata support
// String metadataValue = entry.getEntryMetadata().getValue();
@@ -323,28 +360,37 @@ class W3CBaggagePropagator {
};
}
<R> TraceContextOrSamplingFlags contextWithBaggage(R carrier, TraceContextOrSamplingFlags context,
<R> TraceContextOrSamplingFlags contextWithBaggage(R carrier, TraceContextOrSamplingFlags flags,
Propagation.Getter<R, String> getter) {
BaggagePropagation.FactoryBuilder factoryBuilder = factory();
String traceState = getter.get(carrier, TRACE_STATE);
boolean hasTraceState = StringUtils.hasText(traceState);
if (hasTraceState) {
factoryBuilder = factoryBuilder
.add(BaggagePropagationConfig.SingleBaggageField.remote(TRACE_STATE_BAGGAGE));
}
String baggageHeader = getter.get(carrier, FIELD);
if (baggageHeader == null) {
return context;
List<AbstractMap.SimpleEntry<BaggageInScope, String>> pairs = baggageHeader == null || baggageHeader.isEmpty()
? Collections.emptyList() : addBaggageToContext(baggageHeader);
Set<String> names = pairs.stream().map(e -> e.getKey().name()).collect(Collectors.toSet());
for (String name : names) {
factoryBuilder = factoryBuilder.add(BaggagePropagationConfig.SingleBaggageField
.remote(((BraveBaggageInScope) this.braveBaggageManager.createBaggage(name)).unwrap()));
}
if (baggageHeader.isEmpty()) {
return context;
TraceContext decoratedContext = factoryBuilder.build().decorate(flags.context());
if (hasTraceState) {
BaggageInScope baggageInScope = this.braveBaggageManager.createBaggage(TRACE_STATE);
baggageInScope.set(new BraveTraceContext(decoratedContext), traceState);
}
TraceContextOrSamplingFlags.Builder builder = context.toBuilder();
List<AbstractMap.SimpleEntry<BaggageField, String>> pairs = addBaggageToContext(baggageHeader, builder);
TraceContextOrSamplingFlags built = builder.build();
pairs.forEach(e -> {
BaggageField baggage = e.getKey();
baggage.updateValue(built, e.getValue());
BaggageField baggage = ((BraveBaggageInScope) e.getKey()).unwrap();
baggage.updateValue(decoratedContext, e.getValue());
});
return built;
return TraceContextOrSamplingFlags.create(decoratedContext);
}
List<AbstractMap.SimpleEntry<BaggageField, String>> addBaggageToContext(String baggageHeader,
TraceContextOrSamplingFlags.Builder builder) {
List<AbstractMap.SimpleEntry<BaggageField, String>> pairs = new ArrayList<>();
List<AbstractMap.SimpleEntry<BaggageInScope, String>> addBaggageToContext(String baggageHeader) {
List<AbstractMap.SimpleEntry<BaggageInScope, String>> pairs = new ArrayList<>();
String[] entries = baggageHeader.split(",");
for (String entry : entries) {
int beginningOfMetadata = entry.indexOf(";");
@@ -357,8 +403,7 @@ class W3CBaggagePropagator {
String key = keyAndValue[i].trim();
String value = keyAndValue[i + 1].trim();
BaggageInScope baggage = this.braveBaggageManager.createBaggage(key);
BaggageField field = ((BraveBaggageInScope) baggage).unwrap();
pairs.add(new AbstractMap.SimpleEntry<>(field, value));
pairs.add(new AbstractMap.SimpleEntry<>(baggage, value));
}
catch (Exception e) {
if (log.isDebugEnabled()) {
@@ -368,11 +413,6 @@ class W3CBaggagePropagator {
}
}
}
// TODO: [OTEL] Magic number for max dynamic entries
builder.addExtra(BaggageFields
.newFactory(pairs.stream().map(AbstractMap.SimpleEntry::getKey).collect(Collectors.toList()),
pairs.size() * 2)
.create());
return pairs;
}

View File

@@ -51,7 +51,7 @@ class W3CBaggagePropagatorTest {
TraceContextOrSamplingFlags contextWithBaggage = propagator.contextWithBaggage(carrier, context, Map::get);
assertThat(contextWithBaggage).isSameAs(context);
assertThat(contextWithBaggage).isEqualTo(context);
}
@Test
@@ -62,7 +62,7 @@ class W3CBaggagePropagatorTest {
TraceContextOrSamplingFlags contextWithBaggage = propagator.contextWithBaggage(carrier, context, Map::get);
assertThat(contextWithBaggage).isSameAs(context);
assertThat(contextWithBaggage).isEqualTo(context);
}
@Test

View File

@@ -17,11 +17,14 @@
package org.springframework.cloud.sleuth.brave.bridge;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import brave.baggage.BaggageField;
import brave.internal.baggage.BaggageFields;
import brave.propagation.Propagation;
import brave.propagation.TraceContext;
import brave.propagation.TraceContextOrSamplingFlags;
@@ -54,6 +57,8 @@ class W3CPropagationTest {
private static final String TRACESTATE_NOT_DEFAULT_ENCODING_WITH_SPACES = "bar=baz , foo=bar";
private static final String TRACESTATE_HEADER = "sappp=CwAAmEnGj0gThK52TCXZ270X8nBhc3Nwb3J0LWFwcABQT1NU";
private final W3CPropagation w3CPropagation = new W3CPropagation(new BraveBaggageManager(), new ArrayList<>());
@Test
@@ -83,6 +88,20 @@ class W3CPropagationTest {
assertThat(carrier).containsExactly(entry(TRACE_PARENT, TRACEPARENT_HEADER_SAMPLED));
}
@Test
void inject_tracestate() {
Map<String, String> carrier = new LinkedHashMap<>();
BaggageField traceStateField = BaggageField.create(TRACE_STATE);
BaggageField mybaggageField = BaggageField.create("mybaggage");
TraceContext traceContext = sampledTraceContext()
.addExtra(BaggageFields.newFactory(Arrays.asList(traceStateField, mybaggageField), 2).create()).build();
traceStateField.updateValue(traceContext, TRACESTATE_HEADER);
mybaggageField.updateValue(traceContext, "mybaggagevalue");
w3CPropagation.injector((ignored, key, value) -> carrier.put(key, value)).inject(traceContext, carrier);
assertThat(carrier).containsEntry("baggage", "mybaggage=mybaggagevalue").containsEntry("tracestate",
"sappp=CwAAmEnGj0gThK52TCXZ270X8nBhc3Nwb3J0LWFwcABQT1NU");
}
@Test
void inject_NotSampledContext() {
Map<String, String> carrier = new LinkedHashMap<>();
@@ -163,6 +182,19 @@ class W3CPropagationTest {
.isEqualTo(sharedTraceContext().sampled(false).build());
}
@Test
void extract_tracestate_shouldNotBePartOfBaggage() {
Map<String, String> carrier = new LinkedHashMap<>();
carrier.put(TRACE_PARENT, TRACEPARENT_HEADER_NOT_SAMPLED);
carrier.put(TRACE_STATE, TRACESTATE_HEADER);
carrier.put("baggage", "mybaggage=mybaggagevalue");
TraceContext context = w3CPropagation.extractor(getter).extract(carrier).context();
assertThat(BaggageField.getByName(context, TRACE_STATE)).isNotNull();
assertThat(BaggageField.getByName(context, "mybaggage").getValue(context)).isEqualTo("mybaggagevalue");
}
@Test
void extract_EmptyHeader() {
Map<String, String> invalidHeaders = new LinkedHashMap<>();