Skip to content

Commit c943e4c

Browse files
authored
Switches ID encoding to fixed-length (#450)
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. Fixes #449
1 parent eab6d39 commit c943e4c

File tree

5 files changed

+35
-13
lines changed

5 files changed

+35
-13
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
@@ -453,12 +453,34 @@ public boolean isExportable() {
453453
}
454454

455455
/**
456-
* Represents given long id as hex string
456+
* Represents given long id as 16-character lower-hex string
457457
*/
458458
public static String idToHex(long id) {
459-
return Long.toHexString(id);
459+
char[] data = new char[16];
460+
writeHexLong(data, 0, id);
461+
return new String(data);
460462
}
461463

464+
/** Inspired by {@code okio.Buffer.writeLong} */
465+
static void writeHexLong(char[] data, int pos, long v) {
466+
writeHexByte(data, pos + 0, (byte) ((v >>> 56L) & 0xff));
467+
writeHexByte(data, pos + 2, (byte) ((v >>> 48L) & 0xff));
468+
writeHexByte(data, pos + 4, (byte) ((v >>> 40L) & 0xff));
469+
writeHexByte(data, pos + 6, (byte) ((v >>> 32L) & 0xff));
470+
writeHexByte(data, pos + 8, (byte) ((v >>> 24L) & 0xff));
471+
writeHexByte(data, pos + 10, (byte) ((v >>> 16L) & 0xff));
472+
writeHexByte(data, pos + 12, (byte) ((v >>> 8L) & 0xff));
473+
writeHexByte(data, pos + 14, (byte) (v & 0xff));
474+
}
475+
476+
static void writeHexByte(char[] data, int pos, byte b) {
477+
data[pos + 0] = HEX_DIGITS[(b >> 4) & 0xf];
478+
data[pos + 1] = HEX_DIGITS[b & 0xf];
479+
}
480+
481+
static final char[] HEX_DIGITS =
482+
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
483+
462484
/**
463485
* Parses a 1 to 32 character lower-hex string with no prefix into an unsigned long, tossing any
464486
* 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
@@ -36,12 +36,12 @@
3636
public class SpanTests {
3737

3838
@Test
39-
public void should_convert_long_to_hex_string() throws Exception {
39+
public void should_convert_long_to_16_character_hex_string() throws Exception {
4040
long someLong = 123123L;
4141

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

44-
then(hexString).isEqualTo("1e0f3");
44+
then(hexString).isEqualTo("000000000001e0f3");
4545
}
4646

4747
@Test

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ public void should_set_tracing_headers_on_the_context_when_there_is_a_span() thr
6565
this.customizer.inject(this.span, this.customizer.toSpanTextMap(requestBuilder));
6666

6767
HttpUriRequest request = requestBuilder.build();
68-
thenThereIsAHeaderWithNameAndValue(request, Span.SPAN_ID_NAME, "1");
69-
thenThereIsAHeaderWithNameAndValue(request, Span.TRACE_ID_NAME, "2");
70-
thenThereIsAHeaderWithNameAndValue(request, Span.PARENT_ID_NAME, "3");
68+
thenThereIsAHeaderWithNameAndValue(request, Span.SPAN_ID_NAME, "0000000000000001");
69+
thenThereIsAHeaderWithNameAndValue(request, Span.TRACE_ID_NAME, "0000000000000002");
70+
thenThereIsAHeaderWithNameAndValue(request, Span.PARENT_ID_NAME, "0000000000000003");
7171
thenThereIsAHeaderWithNameAndValue(request, Span.PROCESS_ID_NAME, "processId");
7272
}
7373

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ public void should_set_tracing_headers_on_the_context_when_there_is_a_span() thr
6262
this.customizer.inject(this.span, this.customizer.toSpanTextMap(requestBuilder));
6363

6464
Request request = requestBuilder.build();
65-
thenThereIsAHeaderWithNameAndValue(request, Span.SPAN_ID_NAME, "1");
66-
thenThereIsAHeaderWithNameAndValue(request, Span.TRACE_ID_NAME, "2");
67-
thenThereIsAHeaderWithNameAndValue(request, Span.PARENT_ID_NAME, "3");
65+
thenThereIsAHeaderWithNameAndValue(request, Span.SPAN_ID_NAME, "0000000000000001");
66+
thenThereIsAHeaderWithNameAndValue(request, Span.TRACE_ID_NAME, "0000000000000002");
67+
thenThereIsAHeaderWithNameAndValue(request, Span.PARENT_ID_NAME, "0000000000000003");
6868
thenThereIsAHeaderWithNameAndValue(request, Span.PROCESS_ID_NAME, "processId");
6969
}
7070

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ public void should_set_tracing_headers_on_the_context_when_there_is_a_span() thr
6262
this.customizer.inject(this.span, this.customizer.toSpanTextMap(requestBuilder));
6363

6464
HttpRequest request = requestBuilder.build();
65-
thenThereIsAHeaderWithNameAndValue(request, Span.SPAN_ID_NAME, "1");
66-
thenThereIsAHeaderWithNameAndValue(request, Span.TRACE_ID_NAME, "2");
67-
thenThereIsAHeaderWithNameAndValue(request, Span.PARENT_ID_NAME, "3");
65+
thenThereIsAHeaderWithNameAndValue(request, Span.SPAN_ID_NAME, "0000000000000001");
66+
thenThereIsAHeaderWithNameAndValue(request, Span.TRACE_ID_NAME, "0000000000000002");
67+
thenThereIsAHeaderWithNameAndValue(request, Span.PARENT_ID_NAME, "0000000000000003");
6868
thenThereIsAHeaderWithNameAndValue(request, Span.PROCESS_ID_NAME, "processId");
6969
}
7070

0 commit comments

Comments
 (0)