Updated the implementation to contain all b3 propagation mechanism; fixes gh-1077
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2013-2018 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
|
||||
*
|
||||
* http://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.cloud.sleuth;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Utility class to retrieve tracing ids from headers
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.3.5
|
||||
*/
|
||||
public final class B3Utils {
|
||||
|
||||
/**
|
||||
* Tries to retrieve trace id from b3 header. Falls back to standard header
|
||||
* if there's nothing there in b3 header
|
||||
*/
|
||||
public static String toB3String(Span span) {
|
||||
String traceId = span.traceIdString();
|
||||
String spanId = Span.idToHex(span.getSpanId());
|
||||
boolean sampled = span.isExportable();
|
||||
List<Long> parents = span.getParents();
|
||||
StringBuilder b3 = new StringBuilder()
|
||||
.append(traceId).append("-")
|
||||
.append(spanId).append("-")
|
||||
.append(sampled ? Span.SPAN_SAMPLED : Span.SPAN_NOT_SAMPLED);
|
||||
if (parents != null && !parents.isEmpty()) {
|
||||
b3 = b3.append("-").append(Span.idToHex(parents.get(0)));
|
||||
}
|
||||
return b3.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to retrieve trace id from b3 header. Falls back to standard header
|
||||
* if there's nothing there in b3 header
|
||||
*/
|
||||
public static String traceId(String b3HeaderName,
|
||||
String fallbackHeaderName, Map<String, String> carrier) {
|
||||
String b3 = carrier.get(b3HeaderName);
|
||||
if (StringUtils.hasText(b3)) {
|
||||
String[] split = b3.split("-");
|
||||
if (split.length > 1) {
|
||||
return split[0];
|
||||
}
|
||||
}
|
||||
return carrier.get(fallbackHeaderName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to retrieve span id from b3 header. Falls back to standard header
|
||||
* if there's nothing there in b3 header
|
||||
*/
|
||||
public static String spanId(String b3HeaderName,
|
||||
String fallbackHeaderName, Map<String, String> carrier) {
|
||||
String b3 = carrier.get(b3HeaderName);
|
||||
if (StringUtils.hasText(b3)) {
|
||||
String[] split = b3.split("-");
|
||||
if (split.length > 1) {
|
||||
return split[1];
|
||||
}
|
||||
}
|
||||
return carrier.get(fallbackHeaderName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to retrieve parent span id from b3 header. Falls back to standard header
|
||||
* if there's nothing there in b3 header
|
||||
*/
|
||||
public static String parentSpanId(String b3HeaderName,
|
||||
String fallbackHeaderName, Map<String, String> carrier) {
|
||||
String b3 = carrier.get(b3HeaderName);
|
||||
if (StringUtils.hasText(b3)) {
|
||||
String[] split = b3.split("-");
|
||||
if (split.length == 4) {
|
||||
return split[3];
|
||||
}
|
||||
}
|
||||
return carrier.get(fallbackHeaderName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to retrieve sample flag from b3 header. Falls back to standard span flag header
|
||||
* and sampled header, if there's nothing there in b3 header
|
||||
*/
|
||||
public static Sampled sampled(String b3HeaderName,
|
||||
String fallbackSampledHeaderName, String fallbackFlagsHeaderName,
|
||||
Map<String, String> carrier) {
|
||||
String b3 = carrier.get(b3HeaderName);
|
||||
if (StringUtils.hasText(b3)) {
|
||||
String[] split = b3.split("-");
|
||||
if (split.length > 2) {
|
||||
return Sampled.from(split[2]);
|
||||
}
|
||||
}
|
||||
String fallbackFlag = carrier.get(fallbackFlagsHeaderName);
|
||||
if (Span.SPAN_SAMPLED.equals(fallbackFlag)) {
|
||||
return Sampled.DEBUG;
|
||||
}
|
||||
return Sampled.from(carrier.get(fallbackSampledHeaderName));
|
||||
}
|
||||
|
||||
public enum Sampled {
|
||||
SAMPLED('1'), NOT_SAMPLED('0'), DEBUG('d');
|
||||
|
||||
final char sampledChar;
|
||||
|
||||
Sampled(char sampledChar) {
|
||||
this.sampledChar = sampledChar;
|
||||
}
|
||||
|
||||
static Sampled from(String value) {
|
||||
if (StringUtils.hasText(value)) {
|
||||
switch (value) {
|
||||
case "1" : return SAMPLED;
|
||||
case "0" : return NOT_SAMPLED;
|
||||
case "d" : return DEBUG;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return String.valueOf(this.sampledChar);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,10 +3,10 @@ package org.springframework.cloud.sleuth.instrument.messaging;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import org.springframework.cloud.sleuth.B3Utils;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanTextMap;
|
||||
import org.springframework.cloud.sleuth.util.TextMapUtil;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Default implementation for messaging
|
||||
@@ -62,9 +62,9 @@ public class HeaderBasedMessagingExtractor implements MessagingSpanTextMapExtrac
|
||||
.traceIdHigh(traceId.length() == 32 ? Span.hexToId(traceId, 0) : 0)
|
||||
.traceId(Span.hexToId(traceId))
|
||||
.spanId(Span.hexToId(spanId(carrier)));
|
||||
String flags = carrier.get(TraceMessageHeaders.SPAN_FLAGS_NAME);
|
||||
boolean debug = Span.SPAN_SAMPLED.equals(flags);
|
||||
boolean spanSampled = Span.SPAN_SAMPLED.equals(sampled(carrier));
|
||||
B3Utils.Sampled sampled = sampled(carrier);
|
||||
boolean debug = sampled == B3Utils.Sampled.DEBUG;
|
||||
boolean spanSampled = sampled == B3Utils.Sampled.SAMPLED;
|
||||
if (debug) {
|
||||
spanBuilder.exportable(true);
|
||||
} else {
|
||||
@@ -90,36 +90,19 @@ public class HeaderBasedMessagingExtractor implements MessagingSpanTextMapExtrac
|
||||
}
|
||||
|
||||
private String traceId(Map<String, String> carrier) {
|
||||
String b3 = carrier.get(TraceMessageHeaders.B3_NAME);
|
||||
if (StringUtils.hasText(b3)) {
|
||||
String[] split = b3.split("-");
|
||||
if (split.length == 3) {
|
||||
return split[0];
|
||||
}
|
||||
}
|
||||
return carrier.get(TraceMessageHeaders.TRACE_ID_NAME);
|
||||
return B3Utils.traceId(TraceMessageHeaders.B3_NAME,
|
||||
TraceMessageHeaders.TRACE_ID_NAME, carrier);
|
||||
}
|
||||
|
||||
private String spanId(Map<String, String> carrier) {
|
||||
String b3 = carrier.get(TraceMessageHeaders.B3_NAME);
|
||||
if (StringUtils.hasText(b3)) {
|
||||
String[] split = b3.split("-");
|
||||
if (split.length == 3) {
|
||||
return split[1];
|
||||
}
|
||||
}
|
||||
return carrier.get(TraceMessageHeaders.SPAN_ID_NAME);
|
||||
return B3Utils.spanId(TraceMessageHeaders.B3_NAME,
|
||||
TraceMessageHeaders.SPAN_ID_NAME, carrier);
|
||||
}
|
||||
|
||||
private String sampled(Map<String, String> carrier) {
|
||||
String b3 = carrier.get(TraceMessageHeaders.B3_NAME);
|
||||
if (StringUtils.hasText(b3)) {
|
||||
String[] split = b3.split("-");
|
||||
if (split.length == 3) {
|
||||
return split[2];
|
||||
}
|
||||
}
|
||||
return carrier.get(TraceMessageHeaders.SAMPLED_NAME);
|
||||
private B3Utils.Sampled sampled(Map<String, String> carrier) {
|
||||
return B3Utils.sampled(TraceMessageHeaders.B3_NAME,
|
||||
TraceMessageHeaders.SAMPLED_NAME,
|
||||
TraceMessageHeaders.SPAN_FLAGS_NAME, carrier);
|
||||
}
|
||||
|
||||
boolean hasHeader(Map<String, String> message, String name) {
|
||||
@@ -128,7 +111,7 @@ public class HeaderBasedMessagingExtractor implements MessagingSpanTextMapExtrac
|
||||
|
||||
private void setParentIdIfApplicable(Map<String, String> carrier, Span.SpanBuilder spanBuilder,
|
||||
String spanParentIdHeader) {
|
||||
String parentId = carrier.get(spanParentIdHeader);
|
||||
String parentId = B3Utils.parentSpanId(TraceMessageHeaders.B3_NAME, spanParentIdHeader, carrier);
|
||||
if (parentId != null) {
|
||||
spanBuilder.parent(Span.hexToId(parentId));
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.springframework.cloud.sleuth.instrument.messaging;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.cloud.sleuth.B3Utils;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanTextMap;
|
||||
import org.springframework.cloud.sleuth.TraceKeys;
|
||||
@@ -43,8 +44,7 @@ public class HeaderBasedMessagingInjector implements MessagingSpanTextMapInjecto
|
||||
private void addHeaders(Map<String, String> map, Span span, SpanTextMap textMap) {
|
||||
addHeader(map, textMap, TraceMessageHeaders.TRACE_ID_NAME, span.traceIdString());
|
||||
addHeader(map, textMap, TraceMessageHeaders.SPAN_ID_NAME, Span.idToHex(span.getSpanId()));
|
||||
addHeader(map, textMap, TraceMessageHeaders.B3_NAME, span.traceIdString() + "-" +
|
||||
Span.idToHex(span.getSpanId()) + "-" + (span.isExportable() ? Span.SPAN_SAMPLED : Span.SPAN_NOT_SAMPLED));
|
||||
addHeader(map, textMap, TraceMessageHeaders.B3_NAME, B3Utils.toB3String(span));
|
||||
if (span.isExportable()) {
|
||||
addAnnotations(this.traceKeys, textMap, span);
|
||||
Long parentId = getFirst(span.getParents());
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.Random;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cloud.sleuth.B3Utils;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanTextMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -82,36 +83,16 @@ public class ZipkinHttpSpanExtractor implements HttpSpanExtractor {
|
||||
}
|
||||
|
||||
private String traceId(Map<String, String> carrier) {
|
||||
String b3 = carrier.get(Span.B3_NAME);
|
||||
if (StringUtils.hasText(b3)) {
|
||||
String[] split = b3.split("-");
|
||||
if (split.length == 3) {
|
||||
return split[0];
|
||||
}
|
||||
}
|
||||
return carrier.get(Span.TRACE_ID_NAME);
|
||||
return B3Utils.traceId(Span.B3_NAME, Span.TRACE_ID_NAME, carrier);
|
||||
}
|
||||
|
||||
private String spanId(Map<String, String> carrier) {
|
||||
String b3 = carrier.get(Span.B3_NAME);
|
||||
if (StringUtils.hasText(b3)) {
|
||||
String[] split = b3.split("-");
|
||||
if (split.length == 3) {
|
||||
return split[1];
|
||||
}
|
||||
}
|
||||
return carrier.get(Span.SPAN_ID_NAME);
|
||||
return B3Utils.spanId(Span.B3_NAME, Span.SPAN_ID_NAME, carrier);
|
||||
}
|
||||
|
||||
private String sampled(Map<String, String> carrier) {
|
||||
String b3 = carrier.get(Span.B3_NAME);
|
||||
if (StringUtils.hasText(b3)) {
|
||||
String[] split = b3.split("-");
|
||||
if (split.length == 3) {
|
||||
return split[2];
|
||||
}
|
||||
}
|
||||
return carrier.get(Span.SAMPLED_NAME);
|
||||
private B3Utils.Sampled sampled(Map<String, String> carrier) {
|
||||
return B3Utils.sampled(Span.B3_NAME,
|
||||
Span.SAMPLED_NAME, Span.SPAN_FLAGS, carrier);
|
||||
}
|
||||
|
||||
private String traceIdOrDefaut(Map<String, String> carrier) {
|
||||
@@ -139,18 +120,18 @@ public class ZipkinHttpSpanExtractor implements HttpSpanExtractor {
|
||||
if (StringUtils.hasText(processId)) {
|
||||
span.processId(processId);
|
||||
}
|
||||
String parentId = carrier.get(Span.PARENT_ID_NAME);
|
||||
String parentId = B3Utils.parentSpanId(Span.B3_NAME, Span.PARENT_ID_NAME, carrier);
|
||||
if (parentId != null) {
|
||||
span.parent(Span.hexToId(parentId));
|
||||
}
|
||||
span.remote(true);
|
||||
|
||||
B3Utils.Sampled sampled = sampled(carrier);
|
||||
boolean skip = this.skipPattern
|
||||
.matcher(carrier.get(ZipkinHttpSpanMapper.URI_HEADER)).matches()
|
||||
|| Span.SPAN_NOT_SAMPLED.equals(sampled(carrier));
|
||||
|| sampled == B3Utils.Sampled.NOT_SAMPLED;
|
||||
// trace, span id were retrieved from the headers and span is sampled
|
||||
span.shared(!(skip || idToBeGenerated));
|
||||
boolean debug = Span.SPAN_SAMPLED.equals(carrier.get(Span.SPAN_FLAGS));
|
||||
boolean debug = sampled == B3Utils.Sampled.DEBUG;
|
||||
if (debug) {
|
||||
span.exportable(true);
|
||||
} else if (skip) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.springframework.cloud.sleuth.instrument.web;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.cloud.sleuth.B3Utils;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanTextMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -19,7 +20,7 @@ public class ZipkinHttpSpanInjector implements HttpSpanInjector {
|
||||
@Override
|
||||
public void inject(Span span, SpanTextMap map) {
|
||||
Map<String, String> carrier = SPAN_CARRIER_MAPPER.convert(map);
|
||||
setHeader(map, carrier, Span.B3_NAME, b3(span));
|
||||
setHeader(map, carrier, Span.B3_NAME, B3Utils.toB3String(span));
|
||||
setHeader(map, carrier, Span.TRACE_ID_NAME, span.traceIdString());
|
||||
setIdHeader(map, carrier, Span.SPAN_ID_NAME, span.getSpanId());
|
||||
setHeader(map, carrier, Span.SAMPLED_NAME, span.isExportable() ? Span.SPAN_SAMPLED : Span.SPAN_NOT_SAMPLED);
|
||||
@@ -31,11 +32,6 @@ public class ZipkinHttpSpanInjector implements HttpSpanInjector {
|
||||
}
|
||||
}
|
||||
|
||||
private String b3(Span span) {
|
||||
return span.traceIdString() + "-" + Span.idToHex(span.getSpanId()) + "-" +
|
||||
(span.isExportable() ? Span.SPAN_SAMPLED : Span.SPAN_NOT_SAMPLED);
|
||||
}
|
||||
|
||||
private String prefixedKey(String key) {
|
||||
if (key.startsWith(Span.SPAN_BAGGAGE_HEADER_PREFIX
|
||||
+ ZipkinHttpSpanMapper.HEADER_DELIMITER)) {
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2013-2018 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
|
||||
*
|
||||
* http://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.cloud.sleuth;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.assertj.core.api.BDDAssertions;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class B3UtilsTest {
|
||||
|
||||
@Test public void should_build_a_b3_string_without_parent_span() {
|
||||
Span span = Span.builder()
|
||||
.traceId(1L)
|
||||
.spanId(2L)
|
||||
.exportable(true).build();
|
||||
|
||||
String b3String = B3Utils.toB3String(span);
|
||||
|
||||
BDDAssertions.then(b3String).isEqualTo("0000000000000001-0000000000000002-1");
|
||||
}
|
||||
|
||||
@Test public void should_build_a_b3_string_without_parent_span_for_unsampled() {
|
||||
Span span = Span.builder()
|
||||
.traceId(1L)
|
||||
.spanId(2L)
|
||||
.exportable(false).build();
|
||||
|
||||
String b3String = B3Utils.toB3String(span);
|
||||
|
||||
BDDAssertions.then(b3String).isEqualTo("0000000000000001-0000000000000002-0");
|
||||
}
|
||||
|
||||
@Test public void should_build_a_b3_string_with_parent_span() {
|
||||
Span span = Span.builder()
|
||||
.traceId(1L)
|
||||
.spanId(2L)
|
||||
.parent(3L)
|
||||
.exportable(true).build();
|
||||
|
||||
String b3String = B3Utils.toB3String(span);
|
||||
|
||||
BDDAssertions.then(b3String).isEqualTo("0000000000000001-0000000000000002-1-0000000000000003");
|
||||
}
|
||||
|
||||
@Test public void should_read_trace_id_from_b3_string() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("b3", "0000000000000001-0000000000000002-1-0000000000000003");
|
||||
|
||||
String id = B3Utils.traceId("b3", "fallback", map);
|
||||
|
||||
BDDAssertions.then(id).isEqualTo("0000000000000001");
|
||||
}
|
||||
|
||||
@Test public void should_read_trace_id_from_fallback() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("fallback", "0000000000000001");
|
||||
|
||||
String id = B3Utils.traceId("b3", "fallback", map);
|
||||
|
||||
BDDAssertions.then(id).isEqualTo("0000000000000001");
|
||||
}
|
||||
|
||||
@Test public void should_read_span_id_from_b3_string() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("b3", "0000000000000001-0000000000000002-1-0000000000000003");
|
||||
|
||||
String id = B3Utils.spanId("b3", "fallback", map);
|
||||
|
||||
BDDAssertions.then(id).isEqualTo("0000000000000002");
|
||||
}
|
||||
|
||||
@Test public void should_read_span_id_from_fallback() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("fallback", "0000000000000002");
|
||||
|
||||
String id = B3Utils.spanId("b3", "fallback", map);
|
||||
|
||||
BDDAssertions.then(id).isEqualTo("0000000000000002");
|
||||
}
|
||||
|
||||
@Test public void should_read_parent_id_from_b3_string() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("b3", "0000000000000001-0000000000000002-1-0000000000000003");
|
||||
|
||||
String id = B3Utils.parentSpanId("b3", "fallback", map);
|
||||
|
||||
BDDAssertions.then(id).isEqualTo("0000000000000003");
|
||||
}
|
||||
|
||||
@Test public void should_read_parent_id_from_fallback() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("fallback", "0000000000000003");
|
||||
|
||||
String id = B3Utils.parentSpanId("b3", "fallback", map);
|
||||
|
||||
BDDAssertions.then(id).isEqualTo("0000000000000003");
|
||||
}
|
||||
|
||||
@Test public void should_read_sampled_id_from_b3_string() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("b3", "0000000000000001-0000000000000002-1-0000000000000003");
|
||||
|
||||
B3Utils.Sampled sampled = B3Utils.sampled("b3", "fallbackSampled",
|
||||
"fallbackFlags", map);
|
||||
|
||||
BDDAssertions.then(sampled).isEqualTo(B3Utils.Sampled.SAMPLED);
|
||||
}
|
||||
|
||||
@Test public void should_read_not_sampled_id_from_b3_string() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("b3", "0000000000000001-0000000000000002-0-0000000000000003");
|
||||
|
||||
B3Utils.Sampled sampled = B3Utils.sampled("b3", "fallbackSampled",
|
||||
"fallbackFlags", map);
|
||||
|
||||
BDDAssertions.then(sampled).isEqualTo(B3Utils.Sampled.NOT_SAMPLED);
|
||||
}
|
||||
|
||||
@Test public void should_read_debug_sampled_id_from_b3_string() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("b3", "0000000000000001-0000000000000002-d-0000000000000003");
|
||||
|
||||
B3Utils.Sampled sampled = B3Utils.sampled("b3", "fallbackSampled",
|
||||
"fallbackFlags", map);
|
||||
|
||||
BDDAssertions.then(sampled).isEqualTo(B3Utils.Sampled.DEBUG);
|
||||
}
|
||||
|
||||
@Test public void should_read_sampled_id_from_fallback() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("fallbackSampled", "1");
|
||||
|
||||
B3Utils.Sampled sampled = B3Utils.sampled("b3", "fallbackSampled",
|
||||
"fallbackFlags", map);
|
||||
|
||||
BDDAssertions.then(sampled).isEqualTo(B3Utils.Sampled.SAMPLED);
|
||||
}
|
||||
|
||||
@Test public void should_read_not_sampled_id_from_fallback() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("fallbackSampled", "0");
|
||||
|
||||
B3Utils.Sampled sampled = B3Utils.sampled("b3", "fallbackSampled",
|
||||
"fallbackFlags", map);
|
||||
|
||||
BDDAssertions.then(sampled).isEqualTo(B3Utils.Sampled.NOT_SAMPLED);
|
||||
}
|
||||
|
||||
@Test public void should_read_debug_id_from_fallback() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("fallbackFlags", "1");
|
||||
|
||||
B3Utils.Sampled sampled = B3Utils.sampled("b3", "fallbackSampled",
|
||||
"fallbackFlags", map);
|
||||
|
||||
BDDAssertions.then(sampled).isEqualTo(B3Utils.Sampled.DEBUG);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import java.util.Objects;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
public class SpanAssert extends AbstractAssert<SpanAssert, Span> {
|
||||
@@ -45,6 +46,18 @@ public class SpanAssert extends AbstractAssert<SpanAssert, Span> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SpanAssert hasParentSpanIdEqualTo(Long spanId) {
|
||||
isNotNull();
|
||||
Assertions.assertThat(this.actual.getParents()).isNotEmpty();
|
||||
Long parentSpanId = this.actual.getParents().get(0);
|
||||
if (!Objects.equals(parentSpanId, spanId)) {
|
||||
String message = String.format("Expected span's parent spanId to be <%s> but was <%s>", spanId, parentSpanId);
|
||||
log.error(message);
|
||||
failWithMessage(message);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public SpanAssert hasSpanIdEqualTo(Long spanId) {
|
||||
isNotNull();
|
||||
if (!Objects.equals(this.actual.getSpanId(), spanId)) {
|
||||
|
||||
@@ -32,7 +32,25 @@ import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then;
|
||||
public class HeaderBasedMessagingExtractorTests {
|
||||
|
||||
@Test
|
||||
public void b3HeadersTakePrecedenceOverAnyOtherHeaders() {
|
||||
public void simpleB3HeadersTakePrecedenceOverAnyOtherHeaders() {
|
||||
HeaderBasedMessagingExtractor extractor = new HeaderBasedMessagingExtractor();
|
||||
SpanTextMap spanTextMap = spanTextMap();
|
||||
spanTextMap.put(TraceMessageHeaders.B3_NAME, "0000000000000005-0000000000000004");
|
||||
spanTextMap.put(TraceMessageHeaders.SPAN_ID_NAME, Span.idToHex(20L));
|
||||
spanTextMap.put(TraceMessageHeaders.TRACE_ID_NAME, Span.idToHex(30L));
|
||||
spanTextMap.put(TraceMessageHeaders.SAMPLED_NAME, "1");
|
||||
|
||||
Span span = extractor.joinTrace(spanTextMap);
|
||||
|
||||
then(span)
|
||||
.isNotNull()
|
||||
.hasTraceIdEqualTo(5L)
|
||||
.hasSpanIdEqualTo(4L)
|
||||
.isExportable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void b3HeadersWithSampledTakePrecedenceOverAnyOtherHeaders() {
|
||||
HeaderBasedMessagingExtractor extractor = new HeaderBasedMessagingExtractor();
|
||||
SpanTextMap spanTextMap = spanTextMap();
|
||||
spanTextMap.put(TraceMessageHeaders.B3_NAME, "0000000000000005-0000000000000004-1");
|
||||
@@ -49,6 +67,45 @@ public class HeaderBasedMessagingExtractorTests {
|
||||
.isExportable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void b3HeadersWithDebugSampledTakePrecedenceOverAnyOtherHeaders() {
|
||||
HeaderBasedMessagingExtractor extractor = new HeaderBasedMessagingExtractor();
|
||||
SpanTextMap spanTextMap = spanTextMap();
|
||||
spanTextMap.put(TraceMessageHeaders.B3_NAME, "0000000000000005-0000000000000004-d");
|
||||
spanTextMap.put(TraceMessageHeaders.SPAN_ID_NAME, Span.idToHex(20L));
|
||||
spanTextMap.put(TraceMessageHeaders.TRACE_ID_NAME, Span.idToHex(30L));
|
||||
spanTextMap.put(TraceMessageHeaders.SAMPLED_NAME, "0");
|
||||
spanTextMap.put(TraceMessageHeaders.SPAN_FLAGS_NAME, "0");
|
||||
|
||||
Span span = extractor.joinTrace(spanTextMap);
|
||||
|
||||
then(span)
|
||||
.isNotNull()
|
||||
.hasTraceIdEqualTo(5L)
|
||||
.hasSpanIdEqualTo(4L)
|
||||
.isExportable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void b3HeadersWithParentSpanIdTakePrecedenceOverAnyOtherHeaders() {
|
||||
HeaderBasedMessagingExtractor extractor = new HeaderBasedMessagingExtractor();
|
||||
SpanTextMap spanTextMap = spanTextMap();
|
||||
spanTextMap.put(TraceMessageHeaders.B3_NAME, "0000000000000005-0000000000000004-1-0000000000000003");
|
||||
spanTextMap.put(TraceMessageHeaders.SPAN_ID_NAME, Span.idToHex(20L));
|
||||
spanTextMap.put(TraceMessageHeaders.TRACE_ID_NAME, Span.idToHex(30L));
|
||||
spanTextMap.put(TraceMessageHeaders.PARENT_ID_NAME, Span.idToHex(60L));
|
||||
spanTextMap.put(TraceMessageHeaders.SAMPLED_NAME, "0");
|
||||
|
||||
Span span = extractor.joinTrace(spanTextMap);
|
||||
|
||||
then(span)
|
||||
.isNotNull()
|
||||
.hasTraceIdEqualTo(5L)
|
||||
.hasSpanIdEqualTo(4L)
|
||||
.hasParentSpanIdEqualTo(3L)
|
||||
.isExportable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void legacyHeadersTakePrecedenceOverB3WhenB3IsInvalid() {
|
||||
HeaderBasedMessagingExtractor extractor = new HeaderBasedMessagingExtractor();
|
||||
|
||||
@@ -40,7 +40,7 @@ public class HeaderBasedMessagingInjectorTests {
|
||||
injector.inject(span, map);
|
||||
|
||||
then(map)
|
||||
.contains(new AbstractMap.SimpleEntry<String, String>(TraceMessageHeaders.B3_NAME, "0000000000000002-0000000000000001-1"))
|
||||
.contains(new AbstractMap.SimpleEntry<String, String>(TraceMessageHeaders.B3_NAME, "0000000000000002-0000000000000001-1-0000000000000003"))
|
||||
.contains(new AbstractMap.SimpleEntry<String, String>(TraceMessageHeaders.SPAN_ID_NAME, Span.idToHex(10L)))
|
||||
.contains(new AbstractMap.SimpleEntry<String, String>(TraceMessageHeaders.TRACE_ID_NAME, Span.idToHex(20L)))
|
||||
.contains(new AbstractMap.SimpleEntry<String, String>(TraceMessageHeaders.PARENT_ID_NAME, Span.idToHex(30L)))
|
||||
|
||||
@@ -82,6 +82,60 @@ public class HttpServletRequestExtractorTests {
|
||||
|
||||
@Test
|
||||
public void should_pick_values_from_b3_if_present() {
|
||||
BDDMockito.given(this.request.getHeaderNames())
|
||||
.willReturn(new Vector<>(Arrays.asList(Span.B3_NAME, Span.TRACE_ID_NAME,
|
||||
Span.SPAN_ID_NAME, Span.PARENT_ID_NAME, Span.SAMPLED_NAME,
|
||||
Span.SPAN_FLAGS)).elements());
|
||||
BDDMockito.given(this.request.getHeader(Span.TRACE_ID_NAME))
|
||||
.willReturn(Span.idToHex(10L));
|
||||
BDDMockito.given(this.request.getHeader(Span.SPAN_ID_NAME))
|
||||
.willReturn(Span.idToHex(20L));
|
||||
BDDMockito.given(this.request.getHeader(Span.PARENT_ID_NAME))
|
||||
.willReturn(Span.idToHex(30L));
|
||||
BDDMockito.given(this.request.getHeader(Span.SAMPLED_NAME))
|
||||
.willReturn(Span.SPAN_SAMPLED);
|
||||
BDDMockito.given(this.request.getHeader(Span.B3_NAME))
|
||||
.willReturn("0000000000000005-0000000000000004");
|
||||
|
||||
Span span = this.extractor.joinTrace(new HttpServletRequestTextMap(this.request));
|
||||
|
||||
then(span)
|
||||
.isNotNull()
|
||||
.hasTraceIdEqualTo(5L)
|
||||
.hasSpanIdEqualTo(4L)
|
||||
.hasParentSpanIdEqualTo(30L)
|
||||
.isExportable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_pick_values_from_b3_with_debug_flag_if_present() {
|
||||
BDDMockito.given(this.request.getHeaderNames())
|
||||
.willReturn(new Vector<>(Arrays.asList(Span.B3_NAME, Span.TRACE_ID_NAME,
|
||||
Span.SPAN_ID_NAME, Span.PARENT_ID_NAME, Span.SAMPLED_NAME,
|
||||
Span.SPAN_FLAGS)).elements());
|
||||
BDDMockito.given(this.request.getHeader(Span.TRACE_ID_NAME))
|
||||
.willReturn(Span.idToHex(10L));
|
||||
BDDMockito.given(this.request.getHeader(Span.SPAN_ID_NAME))
|
||||
.willReturn(Span.idToHex(20L));
|
||||
BDDMockito.given(this.request.getHeader(Span.PARENT_ID_NAME))
|
||||
.willReturn(Span.idToHex(30L));
|
||||
BDDMockito.given(this.request.getHeader(Span.SAMPLED_NAME))
|
||||
.willReturn(Span.SPAN_NOT_SAMPLED);
|
||||
BDDMockito.given(this.request.getHeader(Span.B3_NAME))
|
||||
.willReturn("0000000000000005-0000000000000004-d");
|
||||
|
||||
Span span = this.extractor.joinTrace(new HttpServletRequestTextMap(this.request));
|
||||
|
||||
then(span)
|
||||
.isNotNull()
|
||||
.hasTraceIdEqualTo(5L)
|
||||
.hasSpanIdEqualTo(4L)
|
||||
.hasParentSpanIdEqualTo(30L)
|
||||
.isExportable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_pick_values_from_b3_with_sampled_flag_if_present() {
|
||||
BDDMockito.given(this.request.getHeaderNames())
|
||||
.willReturn(new Vector<>(Arrays.asList(Span.B3_NAME, Span.TRACE_ID_NAME,
|
||||
Span.SPAN_ID_NAME, Span.PARENT_ID_NAME, Span.SAMPLED_NAME,
|
||||
@@ -103,6 +157,34 @@ public class HttpServletRequestExtractorTests {
|
||||
.isNotNull()
|
||||
.hasTraceIdEqualTo(5L)
|
||||
.hasSpanIdEqualTo(4L)
|
||||
.hasParentSpanIdEqualTo(30L)
|
||||
.isExportable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_pick_values_from_b3_with_parent_id_if_present() {
|
||||
BDDMockito.given(this.request.getHeaderNames())
|
||||
.willReturn(new Vector<>(Arrays.asList(Span.B3_NAME, Span.TRACE_ID_NAME,
|
||||
Span.SPAN_ID_NAME, Span.PARENT_ID_NAME, Span.SAMPLED_NAME,
|
||||
Span.SPAN_FLAGS)).elements());
|
||||
BDDMockito.given(this.request.getHeader(Span.TRACE_ID_NAME))
|
||||
.willReturn(Span.idToHex(10L));
|
||||
BDDMockito.given(this.request.getHeader(Span.SPAN_ID_NAME))
|
||||
.willReturn(Span.idToHex(20L));
|
||||
BDDMockito.given(this.request.getHeader(Span.PARENT_ID_NAME))
|
||||
.willReturn(Span.idToHex(30L));
|
||||
BDDMockito.given(this.request.getHeader(Span.SAMPLED_NAME))
|
||||
.willReturn(Span.SPAN_NOT_SAMPLED);
|
||||
BDDMockito.given(this.request.getHeader(Span.B3_NAME))
|
||||
.willReturn("0000000000000005-0000000000000004-1-0000000000000006");
|
||||
|
||||
Span span = this.extractor.joinTrace(new HttpServletRequestTextMap(this.request));
|
||||
|
||||
then(span)
|
||||
.isNotNull()
|
||||
.hasTraceIdEqualTo(5L)
|
||||
.hasSpanIdEqualTo(4L)
|
||||
.hasParentSpanIdEqualTo(6L)
|
||||
.isExportable();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public class ZipkinHttpSpanInjectorTests {
|
||||
|
||||
then(map)
|
||||
.contains(new AbstractMap.SimpleEntry<String, String>(Span.B3_NAME,
|
||||
"0000000000000002-0000000000000001-1"))
|
||||
"0000000000000002-0000000000000001-1-0000000000000003"))
|
||||
.contains(new AbstractMap.SimpleEntry<String, String>(Span.SPAN_ID_NAME, Span.idToHex(10L)))
|
||||
.contains(new AbstractMap.SimpleEntry<String, String>(Span.TRACE_ID_NAME, Span.idToHex(20L)))
|
||||
.contains(new AbstractMap.SimpleEntry<String, String>(Span.PARENT_ID_NAME, Span.idToHex(30L)))
|
||||
|
||||
Reference in New Issue
Block a user