Skip to content

Commit d6bc352

Browse files
authored
Switches ID encoding to fixed-length (1.0.x backport) (#451)
Before, we were using variable encoding for trace and span identifiers. This complicates search for those who are copy/pasting fixed-length IDs provisioned upstream. This moves to standard formatting, while maintaining tolerant reads. The code added will also be used to support 128-bit (32 char) trace IDs. Backport of #450
1 parent a393715 commit d6bc352

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,12 +414,34 @@ public boolean isExportable() {
414414
}
415415

416416
/**
417-
* Represents given long id as hex string
417+
* Represents given long id as 16-character lower-hex string
418418
*/
419419
public static String idToHex(long id) {
420-
return Long.toHexString(id);
420+
char[] data = new char[16];
421+
writeHexLong(data, 0, id);
422+
return new String(data);
421423
}
422424

425+
/** Inspired by {@code okio.Buffer.writeLong} */
426+
static void writeHexLong(char[] data, int pos, long v) {
427+
writeHexByte(data, pos + 0, (byte) ((v >>> 56L) & 0xff));
428+
writeHexByte(data, pos + 2, (byte) ((v >>> 48L) & 0xff));
429+
writeHexByte(data, pos + 4, (byte) ((v >>> 40L) & 0xff));
430+
writeHexByte(data, pos + 6, (byte) ((v >>> 32L) & 0xff));
431+
writeHexByte(data, pos + 8, (byte) ((v >>> 24L) & 0xff));
432+
writeHexByte(data, pos + 10, (byte) ((v >>> 16L) & 0xff));
433+
writeHexByte(data, pos + 12, (byte) ((v >>> 8L) & 0xff));
434+
writeHexByte(data, pos + 14, (byte) (v & 0xff));
435+
}
436+
437+
static void writeHexByte(char[] data, int pos, byte b) {
438+
data[pos + 0] = HEX_DIGITS[(b >> 4) & 0xf];
439+
data[pos + 1] = HEX_DIGITS[b & 0xf];
440+
}
441+
442+
static final char[] HEX_DIGITS =
443+
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
444+
423445
/**
424446
* Parses a 1 to 32 character lower-hex string with no prefix into an unsigned long, tossing any
425447
* bits higher than 64.

spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@
3535
public class SpanTests {
3636

3737
@Test
38-
public void should_convert_long_to_hex_string() throws Exception {
38+
public void should_convert_long_to_16_character_hex_string() throws Exception {
3939
long someLong = 123123L;
4040

4141
String hexString = Span.idToHex(someLong);
4242

43-
then(hexString).isEqualTo("1e0f3");
43+
then(hexString).isEqualTo("000000000001e0f3");
4444
}
4545

4646
@Test

spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactoryTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,13 @@ public void should_attach_trace_headers_to_the_sent_request() throws Exception {
9292

9393
HttpRequest httpRequest = builder.build();
9494
then(httpRequest.getHttpHeaders().getFirstValue(Span.SPAN_ID_NAME))
95-
.isEqualTo("1");
95+
.isEqualTo("0000000000000001");
9696
then(httpRequest.getHttpHeaders().getFirstValue(Span.TRACE_ID_NAME))
97-
.isEqualTo("2");
97+
.isEqualTo("0000000000000002");
9898
then(httpRequest.getHttpHeaders().getFirstValue(Span.SPAN_NAME_NAME))
9999
.isEqualTo("name");
100100
then(httpRequest.getHttpHeaders().getFirstValue(Span.PARENT_ID_NAME))
101-
.isEqualTo("3");
101+
.isEqualTo("0000000000000003");
102102
then(httpRequest.getHttpHeaders().getFirstValue(Span.PROCESS_ID_NAME))
103103
.isEqualTo("processId");
104104
}

0 commit comments

Comments
 (0)