Encodes epoch seconds into first 32bits of a 128-bit trace ID (#724)

Amazon will throw out trace IDs that aren't associated with a recent
timestamp. This encodes the current epoch seconds into the first 32
of a 128-bit trace ID to support conversion to an Amazon Root ID.
This commit is contained in:
Adrian Cole
2017-10-05 21:29:53 +08:00
committed by Marcin Grzejszczak
parent 16bae8232a
commit 981fbd18f1
2 changed files with 32 additions and 2 deletions

View File

@@ -98,7 +98,7 @@ public class DefaultTracer implements Tracer {
else {
long id = createId();
span = Span.builder().name(shortenedName)
.traceIdHigh(this.traceId128 ? createId() : 0L)
.traceIdHigh(this.traceId128 ? createTraceIdHigh() : 0L)
.traceId(id)
.spanId(id).build();
if (sampler == null) {
@@ -171,7 +171,7 @@ public class DefaultTracer implements Tracer {
long id = createId();
if (parent == null) {
Span span = Span.builder().name(shortenedName)
.traceIdHigh(this.traceId128 ? createId() : 0L)
.traceIdHigh(this.traceId128 ? createTraceIdHigh() : 0L)
.traceId(id)
.spanId(id).build();
span = sampledSpan(span, this.defaultSampler);
@@ -208,6 +208,21 @@ public class DefaultTracer implements Tracer {
return span;
}
/**
* Encodes a timestamp into the upper 32-bits, so that it can be converted to an Amazon trace ID.
*
* <p>For example, an Amazon trace ID is composed of the following: {@code |-- 32 bits for epoch
* seconds -- | -- 96 bits for random data -- |}
*
* <p>To support this, {@link Span#getTraceIdHigh() traceIdHigh} holds the epoch seconds and first
* 32 random bits: and {@link Span#getTraceId()} traceId} holds the remaining 64 random bits.
*/
private long createTraceIdHigh() {
long epochSeconds = System.currentTimeMillis() / 1000;
int random = this.random.nextInt();
return (epochSeconds & 0xffffffffL) << 32 | (random & 0xffffffffL);
}
private long createId() {
return this.random.nextLong();
}

View File

@@ -16,6 +16,7 @@
package org.springframework.cloud.sleuth.trace;
import java.util.Date;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -231,6 +232,20 @@ public class DefaultTracerTests {
tracer.close(span);
}
/**
* To support conversion to Amazon trace IDs, the first 32 bits of the trace ID are epoch seconds.
*/
@Test
public void creates128bitTraceIdWithEncodedTimestamp() {
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
this.spanNamer, this.spanLogger, this.spanReporter, true, new TraceKeys());
Span span = tracer.createSpan(bigName());
String traceId = span.traceIdString();
long epochSeconds = Long.parseLong(traceId.substring(0, 8), 16);
then(new Date(epochSeconds * 1000)).isToday();
tracer.close(span);
}
@Test
public void shouldCreateChildOfSpanWithShortenedName() {
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),