Skip to content

Commit

Permalink
Merge pull request #34 from adriancole/report-128
Browse files Browse the repository at this point in the history
Reports 128-bit ids to Zipkin
  • Loading branch information
nicmunroe committed Nov 20, 2016
2 parents 9fa505f + 94c2328 commit 38d8ce8
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 15 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Expand Up @@ -64,7 +64,7 @@ javadocJar.enabled = false
ext {
slf4jVersion = '1.7.7'
servletApiVersion = '3.1.0'
zipkinVersion = '1.11.1'
zipkinVersion = '1.16.2'

junitVersion = '4.11'
mockitoVersion = '1.9.5'
Expand Down
Expand Up @@ -74,13 +74,23 @@ public static String longToUnsignedLowerHexString(long primitiveLong) {

/**
* @param hexString The lowercase hexadecimal string representing an unsigned 64-bit long that you want to convert to a Java long primitive.
* @return The Java long primitive represented by the given lowercase hex string. If the string isn't lowercase hexadecimal encoded or if
* the resulting long wouldn't fit inside 64 bits then a {@link NumberFormatException} will be thrown.
* @return The Java long primitive represented by the given lowercase hex string. If the string isn't lowercase hexadecimal encoded then a
* {@link NumberFormatException} will be thrown. If the string is larger than 64-bits, any higher bits will be ignored.
*/
public static long unsignedLowerHexStringToLong(String hexString) {
return ZipkinHexHelpers.lowerHexToUnsignedLong(hexString);
}

/**
* @param hexString The lowercase hexadecimal string representing an unsigned 64-bit long that you want to convert to a Java long primitive.
* @param index index to read 16 hexadecimal characters from
* @return The Java long primitive represented by the given lowercase hex string. If the string isn't lowercase hexadecimal encoded then a
* {@link NumberFormatException} will be thrown.
*/
public static long unsignedLowerHexStringToLong(String hexString, int index) {
return ZipkinHexHelpers.lowerHexToUnsignedLong(hexString, index);
}

/**
* Converts the given 8 bytes to a long value. Implementation for this taken from {@link java.util.UUID#UUID(byte[])}.
*/
Expand Down Expand Up @@ -116,8 +126,8 @@ protected static Random getRandomInstance(String desiredSecureRandomImplementati

/**
* <p>
* 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)
* The code in this class came from the Zipkin repository v1.16.2
* (https://github.com/openzipkin/zipkin/blob/1.16.2/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).
* </p>
*/
Expand All @@ -136,11 +146,22 @@ public static long lowerHexToUnsignedLong(String lowerHex) {
if (length < 1 || length > 32) throw isntLowerHexLong(lowerHex);

// trim off any high bits
int i = length > 16 ? length - 16 : 0;
int beginIndex = length > 16 ? length - 16 : 0;

return lowerHexToUnsignedLong(lowerHex, beginIndex);
}

/**
* Parses a 16 character lower-hex string with no prefix into an unsigned long, starting at the
* spe index.
*/
static long lowerHexToUnsignedLong(String lowerHex, int index) {
int length = lowerHex.length() - index;
if (length < 1) throw new NumberFormatException("Nothing to parse at index " + index);

long result = 0;
for (; i < length; i++) {
char c = lowerHex.charAt(i);
for (int endIndex = Math.min(index + 16, lowerHex.length()); index < endIndex; index++) {
char c = lowerHex.charAt(index);
result <<= 4;
if (c >= '0' && c <= '9') {
result |= c - '0';
Expand Down
Expand Up @@ -231,7 +231,7 @@ public void longToUnsignedLowerHexString_and_unsignedLowerHexStringToLong_work_a

@DataProvider(value = {
" ", // less than 16 chars
"123e4567-e89b-12d3-a456-426655440000 ", // longer than 32 chars
"123e4567-e89b-12d3-a456-426655440000 ", // UUID format (hyphens and also >32 chars)
"/ ", // before '0' char
": ", // after '9' char
"` ", // before 'a' char
Expand All @@ -240,7 +240,7 @@ public void longToUnsignedLowerHexString_and_unsignedLowerHexStringToLong_work_a
}, splitBy = "\\|")
@Test
public void unsignedLowerHexStringToLong_throws_NumberFormatException_for_illegal_args(final String badHexString) {
// when
// when selecting right-most 16 characters
Throwable ex = catchThrowable(new ThrowableAssert.ThrowingCallable() {
@Override
public void call() throws Throwable {
Expand All @@ -250,5 +250,16 @@ public void call() throws Throwable {

// then
assertThat(ex).isInstanceOf(NumberFormatException.class);

// when selecting 16 characters at offset 0
ex = catchThrowable(new ThrowableAssert.ThrowingCallable() {
@Override
public void call() throws Throwable {
TraceAndSpanIdGenerator.unsignedLowerHexStringToLong(badHexString, 0);
}
});

// then
assertThat(ex).isInstanceOf(NumberFormatException.class);
}
}
Expand Up @@ -25,6 +25,7 @@ public class WingtipsToZipkinSpanConverterDefaultImpl implements WingtipsToZipki

@Override
public zipkin.Span convertWingtipsSpanToZipkinSpan(Span wingtipsSpan, Endpoint zipkinEndpoint, String localComponentNamespace) {
String traceId = wingtipsSpan.getTraceId();
long startEpochMicros = wingtipsSpan.getSpanStartTimeEpochMicros();
long durationMicros = TimeUnit.NANOSECONDS.toMicros(wingtipsSpan.getDurationNanos());

Expand All @@ -33,7 +34,8 @@ public zipkin.Span convertWingtipsSpanToZipkinSpan(Span wingtipsSpan, Endpoint z
.name(wingtipsSpan.getSpanName())
.parentId(nullSafeLong(wingtipsSpan.getParentSpanId()))
.timestamp(startEpochMicros)
.traceId(nullSafeLong(wingtipsSpan.getTraceId()))
.traceIdHigh(traceId.length() == 32 ? nullSafeLong(traceId, 0) : 0)
.traceId(nullSafeLong(traceId))
.duration(durationMicros)
.build();
}
Expand Down Expand Up @@ -73,4 +75,10 @@ protected Long nullSafeLong(String lowerHexStr) {
return TraceAndSpanIdGenerator.unsignedLowerHexStringToLong(lowerHexStr);
}

protected Long nullSafeLong(String lowerHexStr, int index) {
if (lowerHexStr == null)
return null;

return TraceAndSpanIdGenerator.unsignedLowerHexStringToLong(lowerHexStr, index);
}
}
Expand Up @@ -2,9 +2,11 @@

import com.nike.wingtips.Span;

import com.nike.wingtips.TraceAndSpanIdGenerator;
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;

import org.assertj.core.api.ThrowableAssert;
import org.junit.Test;
import org.junit.runner.RunWith;

Expand All @@ -20,6 +22,7 @@
import static com.nike.wingtips.TraceAndSpanIdGenerator.generateId;
import static com.nike.wingtips.TraceAndSpanIdGenerator.unsignedLowerHexStringToLong;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.ThrowableAssert.catchThrowable;

/**
* Tests the functionality of {@link WingtipsToZipkinSpanConverterDefaultImpl}.
Expand Down Expand Up @@ -138,12 +141,13 @@ public void convertWingtipsSpanToZipkinSpan_works_as_expected_for_all_nullable_i
@Test
public void convertWingtipsSpanToZipkinSpan_works_as_expected_for_128_bit_trace_id() {
// given
String hex128Bits = "463ac35c9f6413ad48485a3953bb6124";
String lower64Bits = "48485a3953bb6124";
String high64Bits = "463ac35c9f6413ad";
String low64Bits = "48485a3953bb6124";
String hex128Bits = high64Bits + low64Bits;

String spanName = UUID.randomUUID().toString();
String traceId = hex128Bits;
String spanId = lower64Bits;
String spanId = low64Bits;
long startTimeEpochMicros = Math.abs(random.nextLong());
long durationNanos = Math.abs(random.nextLong());
Endpoint zipkinEndpoint = Endpoint.create(UUID.randomUUID().toString(), 42);
Expand All @@ -154,6 +158,35 @@ public void convertWingtipsSpanToZipkinSpan_works_as_expected_for_128_bit_trace_
zipkin.Span zipkinSpan = impl.convertWingtipsSpanToZipkinSpan(wingtipsSpan, zipkinEndpoint, localComponentNamespace);

// then
assertThat(zipkinSpan.traceId).isEqualTo(unsignedLowerHexStringToLong(lower64Bits));
assertThat(zipkinSpan.traceIdHigh).isEqualTo(unsignedLowerHexStringToLong(high64Bits));
assertThat(zipkinSpan.traceId).isEqualTo(unsignedLowerHexStringToLong(low64Bits));
}

@DataProvider(value = {
" ", // empty trace ID
"123e4567-e89b-12d3-a456-426655440000 " // UUID format (hyphens and also >32 chars)
}, splitBy = "\\|")
@Test
public void convertWingtipsSpanToZipkinSpan_throws_NumberFormatException_for_illegal_args(final String badHexString) {
// given
String spanName = UUID.randomUUID().toString();
String traceId = badHexString;
String spanId = "48485a3953bb6124";
long startTimeEpochMicros = Math.abs(random.nextLong());
long durationNanos = Math.abs(random.nextLong());
final Endpoint zipkinEndpoint = Endpoint.create(UUID.randomUUID().toString(), 42);
final String localComponentNamespace = UUID.randomUUID().toString();
final Span wingtipsSpan = new Span(traceId, null, spanId, spanName, true, null, Span.SpanPurpose.CLIENT, startTimeEpochMicros, null, durationNanos);

// when
Throwable ex = catchThrowable(new ThrowableAssert.ThrowingCallable() {
@Override
public void call() throws Throwable {
impl.convertWingtipsSpanToZipkinSpan(wingtipsSpan, zipkinEndpoint, localComponentNamespace);
}
});

// then
assertThat(ex).isInstanceOf(NumberFormatException.class);
}
}

0 comments on commit 38d8ce8

Please sign in to comment.