diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java index e44e6d44a..394ce657d 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java @@ -414,12 +414,34 @@ public class Span { } /** - * Represents given long id as hex string + * Represents given long id as 16-character lower-hex string */ public static String idToHex(long id) { - return Long.toHexString(id); + char[] data = new char[16]; + writeHexLong(data, 0, id); + return new String(data); } + /** Inspired by {@code okio.Buffer.writeLong} */ + static void writeHexLong(char[] data, int pos, long v) { + writeHexByte(data, pos + 0, (byte) ((v >>> 56L) & 0xff)); + writeHexByte(data, pos + 2, (byte) ((v >>> 48L) & 0xff)); + writeHexByte(data, pos + 4, (byte) ((v >>> 40L) & 0xff)); + writeHexByte(data, pos + 6, (byte) ((v >>> 32L) & 0xff)); + writeHexByte(data, pos + 8, (byte) ((v >>> 24L) & 0xff)); + writeHexByte(data, pos + 10, (byte) ((v >>> 16L) & 0xff)); + writeHexByte(data, pos + 12, (byte) ((v >>> 8L) & 0xff)); + writeHexByte(data, pos + 14, (byte) (v & 0xff)); + } + + static void writeHexByte(char[] data, int pos, byte b) { + data[pos + 0] = HEX_DIGITS[(b >> 4) & 0xf]; + data[pos + 1] = HEX_DIGITS[b & 0xf]; + } + + static final char[] HEX_DIGITS = + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + /** * Parses a 1 to 32 character lower-hex string with no prefix into an unsigned long, tossing any * bits higher than 64. diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTests.java index bed930500..e39c07c8c 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTests.java @@ -35,12 +35,12 @@ import static org.assertj.core.api.BDDAssertions.then; public class SpanTests { @Test - public void should_convert_long_to_hex_string() throws Exception { + public void should_convert_long_to_16_character_hex_string() throws Exception { long someLong = 123123L; String hexString = Span.idToHex(someLong); - then(hexString).isEqualTo("1e0f3"); + then(hexString).isEqualTo("000000000001e0f3"); } @Test diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactoryTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactoryTest.java index f85932401..a87ce8f78 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactoryTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactoryTest.java @@ -93,13 +93,13 @@ public class TraceRestClientRibbonCommandFactoryTest { HttpRequest httpRequest = builder.build(); then(httpRequest.getHttpHeaders().getFirstValue(Span.SPAN_ID_NAME)) - .isEqualTo("1"); + .isEqualTo("0000000000000001"); then(httpRequest.getHttpHeaders().getFirstValue(Span.TRACE_ID_NAME)) - .isEqualTo("2"); + .isEqualTo("0000000000000002"); then(httpRequest.getHttpHeaders().getFirstValue(Span.SPAN_NAME_NAME)) .isEqualTo("name"); then(httpRequest.getHttpHeaders().getFirstValue(Span.PARENT_ID_NAME)) - .isEqualTo("3"); + .isEqualTo("0000000000000003"); then(httpRequest.getHttpHeaders().getFirstValue(Span.PROCESS_ID_NAME)) .isEqualTo("processId"); }