From 45380ad03091fc11546ebd1fb9768d3fbde15012 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Thu, 15 Sep 2016 22:42:49 +0800 Subject: [PATCH] Tolerate reads of 128 bit X-B3-TraceId 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 ex 48485a3953bb6124) as the trace id. See openzipkin/b3-propagation#6 --- build.gradle | 2 +- .../wingtips/TraceAndSpanIdGenerator.java | 26 ++++++++++++------- .../wingtips/TraceAndSpanIdGeneratorTest.java | 14 +++++----- ...sToZipkinSpanConverterDefaultImplTest.java | 23 +++++++++++++++- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/build.gradle b/build.gradle index 6f984c16..65e6f777 100644 --- a/build.gradle +++ b/build.gradle @@ -64,7 +64,7 @@ javadocJar.enabled = false ext { slf4jVersion = '1.7.7' servletApiVersion = '3.1.0' - zipkinVersion = '1.8.4' + zipkinVersion = '1.11.1' junitVersion = '4.11' mockitoVersion = '1.9.5' diff --git a/wingtips-core/src/main/java/com/nike/wingtips/TraceAndSpanIdGenerator.java b/wingtips-core/src/main/java/com/nike/wingtips/TraceAndSpanIdGenerator.java index 1b5cc291..7810f3d8 100644 --- a/wingtips-core/src/main/java/com/nike/wingtips/TraceAndSpanIdGenerator.java +++ b/wingtips-core/src/main/java/com/nike/wingtips/TraceAndSpanIdGenerator.java @@ -116,8 +116,8 @@ protected static Random getRandomInstance(String desiredSecureRandomImplementati /** *

- * The code in this class came from the Zipkin repository v1.7.0 - * (https://github.com/openzipkin/zipkin/blob/master/zipkin/src/main/java/zipkin/internal/Util.java) + * The code in this class came from the Zipkin repository v1.11.1 + * (https://github.com/openzipkin/zipkin/blob/1.11.1/zipkin/src/main/java/zipkin/internal/Util.java) * and licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0). *

*/ @@ -127,14 +127,20 @@ private ZipkinHexHelpers() { // Do nothing } - /** Parses a 1 to 16 character lower-hex string with no prefix int an unsigned long. */ - static long lowerHexToUnsignedLong(String lowerHex) { - char[] array = lowerHex.toCharArray(); - if (array.length < 1 || array.length > 16) { - throw isntLowerHexLong(lowerHex); - } + /** + * 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 lowerHexToUnsignedLong(String lowerHex) { + int length = lowerHex.length(); + if (length < 1 || length > 32) throw isntLowerHexLong(lowerHex); + + // trim off any high bits + int i = length > 16 ? length - 16 : 0; + long result = 0; - for (char c : array) { + for (; i < length; i++) { + char c = lowerHex.charAt(i); result <<= 4; if (c >= '0' && c <= '9') { result |= c - '0'; @@ -149,7 +155,7 @@ static long lowerHexToUnsignedLong(String lowerHex) { static NumberFormatException isntLowerHexLong(String lowerHex) { return new NumberFormatException( - lowerHex + " should be a 1 to 16 character lower-hex string with no prefix"); + lowerHex + " should be a 1 to 32 character lower-hex string with no prefix"); } /** Inspired by {@code okio.Buffer.writeLong} */ diff --git a/wingtips-core/src/test/java/com/nike/wingtips/TraceAndSpanIdGeneratorTest.java b/wingtips-core/src/test/java/com/nike/wingtips/TraceAndSpanIdGeneratorTest.java index b50da952..ef08a5a7 100644 --- a/wingtips-core/src/test/java/com/nike/wingtips/TraceAndSpanIdGeneratorTest.java +++ b/wingtips-core/src/test/java/com/nike/wingtips/TraceAndSpanIdGeneratorTest.java @@ -230,13 +230,13 @@ public void longToUnsignedLowerHexString_and_unsignedLowerHexStringToLong_work_a } @DataProvider(value = { - " ", // less than 16 chars - "12345678901234567 ", // longer than 16 chars - "/ ", // before '0' char - ": ", // after '9' char - "` ", // before 'a' char - "g ", // after 'f' char - "ABCDEF " // uppercase hex chars + " ", // less than 16 chars + "123e4567-e89b-12d3-a456-426655440000 ", // longer than 32 chars + "/ ", // before '0' char + ": ", // after '9' char + "` ", // before 'a' char + "g ", // after 'f' char + "ABCDEF " // uppercase hex chars }, splitBy = "\\|") @Test public void unsignedLowerHexStringToLong_throws_NumberFormatException_for_illegal_args(final String badHexString) { diff --git a/wingtips-zipkin/src/test/java/com/nike/wingtips/zipkin/util/WingtipsToZipkinSpanConverterDefaultImplTest.java b/wingtips-zipkin/src/test/java/com/nike/wingtips/zipkin/util/WingtipsToZipkinSpanConverterDefaultImplTest.java index 483e89e3..8598d252 100644 --- a/wingtips-zipkin/src/test/java/com/nike/wingtips/zipkin/util/WingtipsToZipkinSpanConverterDefaultImplTest.java +++ b/wingtips-zipkin/src/test/java/com/nike/wingtips/zipkin/util/WingtipsToZipkinSpanConverterDefaultImplTest.java @@ -135,4 +135,25 @@ public void convertWingtipsSpanToZipkinSpan_works_as_expected_for_all_nullable_i verifySpanPurposeRelatedStuff(zipkinSpan, wingtipsSpan, zipkinEndpoint, localComponentNamespace); } -} \ No newline at end of file + @Test + public void convertWingtipsSpanToZipkinSpan_works_as_expected_for_128_bit_trace_id() { + // given + String hex128Bits = "463ac35c9f6413ad48485a3953bb6124"; + String lower64Bits = "48485a3953bb6124"; + + String spanName = UUID.randomUUID().toString(); + String traceId = hex128Bits; + String spanId = lower64Bits; + long startTimeEpochMicros = Math.abs(random.nextLong()); + long durationNanos = Math.abs(random.nextLong()); + Endpoint zipkinEndpoint = Endpoint.create(UUID.randomUUID().toString(), 42); + String localComponentNamespace = UUID.randomUUID().toString(); + Span wingtipsSpan = new Span(traceId, null, spanId, spanName, true, null, Span.SpanPurpose.CLIENT, startTimeEpochMicros, null, durationNanos); + + // when + zipkin.Span zipkinSpan = impl.convertWingtipsSpanToZipkinSpan(wingtipsSpan, zipkinEndpoint, localComponentNamespace); + + // then + assertThat(zipkinSpan.traceId).isEqualTo(unsignedLowerHexStringToLong(lower64Bits)); + } +}