Tolerate reads of 128 bit X-B3-TraceId (#408)
The first step of transitioning to 128bit `X-B3-TraceId` is tolerantly reading 32 character long ids by throwing away the high bits (any characters left of 16 characters). This allows the tracing system to more flexibly introduce 128bit trace id support in the future. Ex. when `X-B3-TraceId: 463ac35c9f6413ad48485a3953bb6124` is received, parse the lower 64 bits (right most 16 characters ex48485a3953bb6124) as the trace id.
This commit is contained in:
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.cloud.sleuth;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -421,15 +420,30 @@ public class Span {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents hex string as long
|
||||
* Parses a 1 to 32 character lower-hex string with no prefix into an unsigned long, tossing any
|
||||
* bits higher than 64.
|
||||
*/
|
||||
public static long hexToId(String hexString) {
|
||||
Assert.hasText(hexString, "Can't convert empty hex string to long");
|
||||
try {
|
||||
return new BigInteger(hexString, 16).longValue();
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException("Malformed id [" + hexString + "]", e);
|
||||
int length = hexString.length();
|
||||
if (length < 1 || length > 32) throw new IllegalArgumentException("Malformed id");
|
||||
|
||||
// trim off any high bits
|
||||
int i = length > 16 ? length - 16 : 0;
|
||||
|
||||
long result = 0;
|
||||
for (; i < length; i++) {
|
||||
char c = hexString.charAt(i);
|
||||
result <<= 4;
|
||||
if (c >= '0' && c <= '9') {
|
||||
result |= c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
result |= c - 'a' + 10;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Malformed id");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -52,6 +52,16 @@ public class SpanTests {
|
||||
then(someLong).isEqualTo(123123L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_convert_lower_64bits_of_hex_string_to_long() throws Exception {
|
||||
String hex128Bits = "463ac35c9f6413ad48485a3953bb6124";
|
||||
String lower64Bits = "48485a3953bb6124";
|
||||
|
||||
long someLong = Span.hexToId(hex128Bits);
|
||||
|
||||
then(someLong).isEqualTo(Span.hexToId(lower64Bits));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void should_throw_exception_when_null_string_is_to_be_converted_to_long() throws Exception {
|
||||
Span.hexToId(null);
|
||||
|
||||
@@ -275,6 +275,20 @@ public class TraceChannelInterceptorTests implements MessageHandler {
|
||||
then(TestSpanContextHolder.getCurrentSpan()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void downgrades128bitIdsByDroppingHighBits() {
|
||||
String hex128Bits = "463ac35c9f6413ad48485a3953bb6124";
|
||||
String lower64Bits = "48485a3953bb6124";
|
||||
this.tracedChannel.send(MessageBuilder.withPayload("hi")
|
||||
.setHeader(Span.TRACE_ID_NAME, hex128Bits)
|
||||
.setHeader(Span.SPAN_ID_NAME, Span.idToHex(20L)).build());
|
||||
then(this.message).isNotNull();
|
||||
|
||||
long traceId = Span.hexToId(this.message.getHeaders()
|
||||
.get(TraceMessageHeaders.TRACE_ID_NAME, String.class));
|
||||
then(traceId).isEqualTo(Span.hexToId(lower64Bits));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
static class App {
|
||||
|
||||
@@ -93,4 +93,19 @@ public class HttpServletRequestExtractorTests {
|
||||
then(e).hasMessageContaining("Malformed id");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_downgrade_128bit_trace_id_by_dropping_high_bits() {
|
||||
String hex128Bits = "463ac35c9f6413ad48485a3953bb6124";
|
||||
String lower64Bits = "48485a3953bb6124";
|
||||
|
||||
BDDMockito.given(this.request.getHeader(Span.TRACE_ID_NAME))
|
||||
.willReturn(hex128Bits);
|
||||
BDDMockito.given(this.request.getHeader(Span.SPAN_ID_NAME))
|
||||
.willReturn(lower64Bits);
|
||||
|
||||
Span span = this.extractor.joinTrace(this.request);
|
||||
|
||||
then(span.getTraceId()).isEqualTo(Span.hexToId(lower64Bits));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user