Skip to content

Commit

Permalink
� This is a combination of 2 commits.
Browse files Browse the repository at this point in the history
� This is the 1st commit message:

WIP on converting to String-based SpanContext

don't hand out the byte arrays publicly, but require making copies

make sure to hand out fresh invalid byte arrays.

Use strings for span and trace ids.

Switch over to CharSequence instead of String for the ids

Fix a couple of places that were casting to String

Add some simple wrappers for the generated longs to save converting until the last moment to the character-based representation.

introduce a reusable threadlocal char buffer for generating random ids.

update for changes from upstream

Change the SpanContext to store the ids as Strings internally
Change the id access methods on SpanContext to be clearly labeled as the base16 representations
Add a new create method that allows specifying offsets for traceId and spanId CharSequences

Provide an option for creating a SpanContext from longs or Strings, optionally.

fix a typo

update from upstream

� The commit message #2 will be skipped:

� don't hand out the byte arrays publicly, but require making copies
  • Loading branch information
jwatson committed Sep 1, 2020
1 parent 225acce commit 8a9760c
Show file tree
Hide file tree
Showing 62 changed files with 444 additions and 325 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ private static SpanContext createTestSpanContext(String traceId, String spanId)
TraceFlags sampledTraceOptions = TraceFlags.fromByte(sampledTraceOptionsBytes);
TraceState traceStateDefault = TraceState.builder().build();
return SpanContext.create(
TraceId.fromLowerBase16(traceId, 0),
SpanId.fromLowerBase16(spanId, 0),
TraceId.bytesFromLowerBase16(traceId, 0),
SpanId.bytesFromLowerBase16(spanId, 0),
sampledTraceOptions,
traceStateDefault);
}
Expand Down
46 changes: 41 additions & 5 deletions api/src/main/java/io/opentelemetry/trace/SpanContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public static SpanContext getInvalid() {
* @since 0.1.0
*/
public static SpanContext create(
TraceId traceId, SpanId spanId, TraceFlags traceFlags, TraceState traceState) {
byte[] traceId, byte[] spanId, TraceFlags traceFlags, TraceState traceState) {
return new AutoValue_SpanContext(traceId, spanId, traceFlags, traceState, /* remote=*/ false);
}

Expand All @@ -75,7 +75,7 @@ public static SpanContext create(
* @since 0.1.0
*/
public static SpanContext createFromRemoteParent(
TraceId traceId, SpanId spanId, TraceFlags traceFlags, TraceState traceState) {
byte[] traceId, byte[] spanId, TraceFlags traceFlags, TraceState traceState) {
return new AutoValue_SpanContext(traceId, spanId, traceFlags, traceState, /* remote=*/ true);
}

Expand All @@ -85,15 +85,51 @@ public static SpanContext createFromRemoteParent(
* @return the trace identifier associated with this {@code SpanContext}.
* @since 0.1.0
*/
public abstract TraceId getTraceId();
@SuppressWarnings("mutable")
abstract byte[] getTraceId();

/**
* Returns the trace identifier associated with this {@code SpanContext}.
*
* @return the trace identifier associated with this {@code SpanContext}.
* @since 0.1.0
*/
public byte[] traceId() {
byte[] result = new byte[16];
copyTraceId(result, 0);
return result;
}

/** javadoc me. */
public void copyTraceId(byte[] destination, int destOffset) {
System.arraycopy(getTraceId(), 0, destination, destOffset, 16);
}

/**
* Returns the span identifier associated with this {@code SpanContext}.
*
* @return the span identifier associated with this {@code SpanContext}.
* @since 0.1.0
*/
public abstract SpanId getSpanId();
@SuppressWarnings("mutable")
abstract byte[] getSpanId();

/**
* Returns the span identifier associated with this {@code SpanContext}.
*
* @return the span identifier associated with this {@code SpanContext}.
* @since 0.1.0
*/
public byte[] spanId() {
byte[] result = new byte[8];
copySpanId(result, 0);
return result;
}

/** javadoc me. */
public void copySpanId(byte[] destination, int destOffset) {
System.arraycopy(getSpanId(), 0, destination, destOffset, 8);
}

/**
* Returns the {@code TraceFlags} associated with this {@code SpanContext}.
Expand All @@ -118,7 +154,7 @@ public static SpanContext createFromRemoteParent(
* @since 0.1.0
*/
public boolean isValid() {
return getTraceId().isValid() && getSpanId().isValid();
return TraceId.isValid(getTraceId()) && SpanId.isValid(getSpanId());
}

/**
Expand Down
39 changes: 35 additions & 4 deletions api/src/main/java/io/opentelemetry/trace/SpanId.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package io.opentelemetry.trace;

import io.opentelemetry.internal.Utils;
import java.util.Arrays;
import java.util.Random;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

Expand All @@ -32,7 +34,7 @@ public final class SpanId implements Comparable<SpanId> {
private static final int SIZE = 8;
private static final int BASE16_SIZE = 2 * SIZE;
private static final long INVALID_ID = 0;
private static final SpanId INVALID = new SpanId(INVALID_ID);
private static final byte[] INVALID = new byte[8];

// The internal representation of the SpanId.
private final long id;
Expand Down Expand Up @@ -70,7 +72,7 @@ public static int getSize() {
* @return the invalid {@code SpanId}.
* @since 0.1.0
*/
public static SpanId getInvalid() {
public static byte[] getInvalid() {
return INVALID;
}

Expand All @@ -92,6 +94,13 @@ public static SpanId fromBytes(byte[] src, int srcOffset) {
return new SpanId(BigendianEncoding.longFromByteArray(src, srcOffset));
}

/** javadoc me. */
public static byte[] fromLong(long id) {
byte[] result = new byte[8];
BigendianEncoding.longToByteArray(id, result, 0);
return result;
}

/**
* Copies the byte array representations of the {@code SpanId} into the {@code dest} beginning at
* the {@code destOffset} offset.
Expand Down Expand Up @@ -119,9 +128,13 @@ public void copyBytesTo(byte[] dest, int destOffset) {
* srcOffset}.
* @since 0.1.0
*/
public static SpanId fromLowerBase16(CharSequence src, int srcOffset) {
public static byte[] bytesFromLowerBase16(CharSequence src, int srcOffset) {
Utils.checkNotNull(src, "src");
return new SpanId(BigendianEncoding.longFromBase16String(src, srcOffset));
byte[] result = new byte[8];
// todo: optimize me
long value = BigendianEncoding.longFromBase16String(src, srcOffset);
BigendianEncoding.longToByteArray(value, result, 0);
return result;
}

/**
Expand All @@ -138,6 +151,12 @@ public void copyLowerBase16To(char[] dest, int destOffset) {
BigendianEncoding.longToBase16String(id, dest, destOffset);
}

/** javadoc me. */
public static void copyLowerBase16Into(byte[] spanId, char[] dest, int destOffset) {
BigendianEncoding.longToBase16String(
BigendianEncoding.longFromByteArray(spanId, 0), dest, destOffset);
}

/**
* Returns whether the span identifier is valid. A valid span identifier is an 8-byte array with
* at least one non-zero byte.
Expand All @@ -149,6 +168,11 @@ public boolean isValid() {
return id != INVALID_ID;
}

/** javadoc me. */
public static boolean isValid(byte[] spanId) {
return (spanId.length == SpanId.getSize()) && !Arrays.equals(spanId, SpanId.getInvalid());
}

/**
* Returns the lowercase base16 encoding of this {@code SpanId}.
*
Expand All @@ -161,6 +185,13 @@ public String toLowerBase16() {
return new String(chars);
}

/** javadoc me. */
public static String toLowerBase16(byte[] spanId) {
char[] chars = new char[BASE16_SIZE];
copyLowerBase16Into(spanId, chars, 0);
return new String(chars);
}

@Override
public boolean equals(@Nullable Object obj) {
if (obj == this) {
Expand Down
53 changes: 51 additions & 2 deletions api/src/main/java/io/opentelemetry/trace/TraceId.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package io.opentelemetry.trace;

import io.opentelemetry.internal.Utils;
import java.util.Arrays;
import java.util.Random;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

Expand All @@ -32,7 +34,7 @@ public final class TraceId implements Comparable<TraceId> {
private static final int SIZE = 16;
private static final int BASE16_SIZE = 2 * BigendianEncoding.LONG_BASE16;
private static final long INVALID_ID = 0;
private static final TraceId INVALID = new TraceId(INVALID_ID, INVALID_ID);
private static final byte[] INVALID = new byte[16];

// The internal representation of the TraceId.
private final long idHi;
Expand Down Expand Up @@ -74,7 +76,7 @@ public static int getSize() {
* @return the invalid {@code TraceId}.
* @since 0.1.0
*/
public static TraceId getInvalid() {
public static byte[] getInvalid() {
return INVALID;
}

Expand All @@ -98,6 +100,14 @@ public static TraceId fromBytes(byte[] src, int srcOffset) {
BigendianEncoding.longFromByteArray(src, srcOffset + BigendianEncoding.LONG_BYTES));
}

/** javadoc me. */
public static byte[] fromLongs(long idHi, long idLo) {
byte[] result = new byte[16];
BigendianEncoding.longToByteArray(idHi, result, 0);
BigendianEncoding.longToByteArray(idLo, result, 8);
return result;
}

/**
* Copies the byte array representations of the {@code TraceId} into the {@code dest} beginning at
* the {@code destOffset} offset.
Expand Down Expand Up @@ -133,6 +143,21 @@ public static TraceId fromLowerBase16(CharSequence src, int srcOffset) {
BigendianEncoding.longFromBase16String(src, srcOffset + BigendianEncoding.LONG_BASE16));
}

/** javadoc me. */
public static byte[] bytesFromLowerBase16(CharSequence src, int srcOffset) {
Utils.checkNotNull(src, "src");
byte[] result = new byte[16];

// todo: optimize me
long hi = BigendianEncoding.longFromBase16String(src, srcOffset);
long lo =
BigendianEncoding.longFromBase16String(src, srcOffset + BigendianEncoding.LONG_BASE16);

BigendianEncoding.longToByteArray(hi, result, 0);
BigendianEncoding.longToByteArray(lo, result, 8);
return result;
}

/**
* Copies the lowercase base16 representations of the {@code TraceId} into the {@code dest}
* beginning at the {@code destOffset} offset.
Expand All @@ -148,6 +173,14 @@ public void copyLowerBase16To(char[] dest, int destOffset) {
BigendianEncoding.longToBase16String(idLo, dest, destOffset + BASE16_SIZE / 2);
}

/** javadoc me. */
public static void copyLowerBase16Into(byte[] traceId, char[] dest, int destOffset) {
BigendianEncoding.longToBase16String(
BigendianEncoding.longFromByteArray(traceId, 0), dest, destOffset);
BigendianEncoding.longToBase16String(
BigendianEncoding.longFromByteArray(traceId, 8), dest, destOffset + 16);
}

/**
* Returns whether the {@code TraceId} is valid. A valid trace identifier is a 16-byte array with
* at least one non-zero byte.
Expand All @@ -159,6 +192,11 @@ public boolean isValid() {
return idHi != INVALID_ID || idLo != INVALID_ID;
}

/** javadoc me. */
public static boolean isValid(byte[] traceId) {
return (traceId.length == TraceId.getSize()) && !Arrays.equals(traceId, TraceId.getInvalid());
}

/**
* Returns the lowercase base16 encoding of this {@code TraceId}.
*
Expand All @@ -171,6 +209,13 @@ public String toLowerBase16() {
return new String(chars);
}

/** javadoc me. */
public static String toLowerBase16(byte[] traceId) {
char[] chars = new char[BASE16_SIZE];
copyLowerBase16Into(traceId, chars, 0);
return new String(chars);
}

@Override
public boolean equals(@Nullable Object obj) {
if (obj == this) {
Expand All @@ -197,6 +242,10 @@ public long getTraceRandomPart() {
return idLo;
}

public static long getTraceIdRandomPart(byte[] traceId) {
return BigendianEncoding.longFromByteArray(traceId, 8);
}

@Override
public int hashCode() {
// Copied from Arrays.hashCode(long[])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,13 @@ private static <C> void injectImpl(SpanContext spanContext, C carrier, Setter<C>
chars[0] = VERSION.charAt(0);
chars[1] = VERSION.charAt(1);
chars[2] = TRACEPARENT_DELIMITER;
spanContext.getTraceId().copyLowerBase16To(chars, TRACE_ID_OFFSET);
byte[] traceId = spanContext.traceId();
TraceId.copyLowerBase16Into(traceId, chars, TRACE_ID_OFFSET);

chars[SPAN_ID_OFFSET - 1] = TRACEPARENT_DELIMITER;
spanContext.getSpanId().copyLowerBase16To(chars, SPAN_ID_OFFSET);

byte[] spanId = spanContext.spanId();
SpanId.copyLowerBase16Into(spanId, chars, SPAN_ID_OFFSET);
chars[TRACE_OPTION_OFFSET - 1] = TRACEPARENT_DELIMITER;
spanContext.getTraceFlags().copyLowerBase16To(chars, TRACE_OPTION_OFFSET);
setter.set(carrier, TRACE_PARENT, new String(chars, 0, TRACEPARENT_HEADER_SIZE));
Expand Down Expand Up @@ -152,8 +156,8 @@ private static <C> SpanContext extractImpl(C carrier, Getter<C> getter) {
try {
TraceState traceState = extractTraceState(traceStateHeader);
return SpanContext.createFromRemoteParent(
contextFromParentHeader.getTraceId(),
contextFromParentHeader.getSpanId(),
contextFromParentHeader.traceId(),
contextFromParentHeader.spanId(),
contextFromParentHeader.getTraceFlags(),
traceState);
} catch (IllegalArgumentException e) {
Expand All @@ -178,8 +182,8 @@ private static SpanContext extractContextFromTraceParent(String traceparent) {
}

try {
TraceId traceId = TraceId.fromLowerBase16(traceparent, TRACE_ID_OFFSET);
SpanId spanId = SpanId.fromLowerBase16(traceparent, SPAN_ID_OFFSET);
byte[] traceId = TraceId.bytesFromLowerBase16(traceparent, TRACE_ID_OFFSET);
byte[] spanId = SpanId.bytesFromLowerBase16(traceparent, SPAN_ID_OFFSET);
TraceFlags traceFlags = TraceFlags.fromLowerBase16(traceparent, TRACE_OPTION_OFFSET);
return SpanContext.createFromRemoteParent(traceId, spanId, traceFlags, TRACE_STATE_DEFAULT);
} catch (IllegalArgumentException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,9 @@ class DefaultTracerTest {
private static final String SPAN_NAME = "MySpanName";
private static final byte[] firstBytes =
new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'a'};
private static final byte[] spanBytes = new byte[] {0, 0, 0, 0, 0, 0, 0, 'a'};
private static final SpanContext spanContext =
SpanContext.create(
TraceId.fromBytes(firstBytes, 0),
SpanId.fromBytes(firstBytes, 8),
TraceFlags.getDefault(),
TraceState.getDefault());
SpanContext.create(firstBytes, spanBytes, TraceFlags.getDefault(), TraceState.getDefault());

@Test
void defaultGetCurrentSpan() {
Expand Down
Loading

0 comments on commit 8a9760c

Please sign in to comment.