diff --git a/api/src/main/java/io/opentelemetry/api/trace/ImmutableSpanContext.java b/api/src/main/java/io/opentelemetry/api/trace/ImmutableSpanContext.java new file mode 100644 index 00000000000..b77a41a2d42 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/api/trace/ImmutableSpanContext.java @@ -0,0 +1,51 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.api.trace; + +import com.google.auto.value.AutoValue; +import com.google.auto.value.extension.memoized.Memoized; +import javax.annotation.concurrent.Immutable; + +@Immutable +@AutoValue +abstract class ImmutableSpanContext implements SpanContext { + + private static final SpanContext INVALID = + create( + TraceId.getInvalid(), + SpanId.getInvalid(), + TraceFlags.getDefault(), + TraceState.getDefault(), + /* remote= */ false); + + static SpanContext getInvalid() { + return INVALID; + } + + static SpanContext create( + String traceIdHex, String spanIdHex, byte traceFlags, TraceState traceState, boolean remote) { + return new AutoValue_ImmutableSpanContext( + traceIdHex, spanIdHex, traceFlags, traceState, remote); + } + + @Override + @Memoized + public byte[] getTraceIdBytes() { + return SpanContext.super.getTraceIdBytes(); + } + + @Override + @Memoized + public byte[] getSpanIdBytes() { + return SpanContext.super.getSpanIdBytes(); + } + + @Override + @Memoized + public boolean isValid() { + return SpanContext.super.isValid(); + } +} diff --git a/api/src/main/java/io/opentelemetry/api/trace/SpanContext.java b/api/src/main/java/io/opentelemetry/api/trace/SpanContext.java index 030cc300a84..0f61ce91a09 100644 --- a/api/src/main/java/io/opentelemetry/api/trace/SpanContext.java +++ b/api/src/main/java/io/opentelemetry/api/trace/SpanContext.java @@ -5,8 +5,6 @@ package io.opentelemetry.api.trace; -import com.google.auto.value.AutoValue; -import com.google.auto.value.extension.memoized.Memoized; import javax.annotation.concurrent.Immutable; /** @@ -15,25 +13,24 @@ * trace_id} and {@link SpanId span_id}) associated with the {@link Span} and a set of options * (currently only whether the context is sampled or not), as well as the {@link TraceState * traceState} and the {@link boolean remote} flag. + * + *

Implementations of this interface *must* be immutable and have well-defined value-based + * equals/hashCode implementations. If an implementation does not strictly conform to these + * requirements, behavior of the OpenTelemetry APIs and default SDK cannot be guaranteed. It is + * strongly suggested that you use the implementation that is provided here via {@link + * #create(String, String, byte, TraceState)} or {@link #createFromRemoteParent(String, String, + * byte, TraceState)}. */ @Immutable -@AutoValue -public abstract class SpanContext { - - private static final SpanContext INVALID = - create( - TraceId.getInvalid(), - SpanId.getInvalid(), - TraceFlags.getDefault(), - TraceState.getDefault()); +public interface SpanContext { /** * Returns the invalid {@code SpanContext} that can be used for no-op operations. * * @return the invalid {@code SpanContext}. */ - public static SpanContext getInvalid() { - return INVALID; + static SpanContext getInvalid() { + return ImmutableSpanContext.getInvalid(); } /** @@ -45,15 +42,10 @@ public static SpanContext getInvalid() { * @param traceState the trace state for the span context. * @return a new {@code SpanContext} with the given identifiers and options. */ - public static SpanContext create( + static SpanContext create( String traceIdHex, String spanIdHex, byte traceFlags, TraceState traceState) { - return create(traceIdHex, spanIdHex, traceFlags, traceState, /* remote=*/ false); - } - - private static SpanContext create( - String traceIdHex, String spanIdHex, byte traceFlags, TraceState traceState, boolean remote) { - return new AutoValue_SpanContext( - traceIdHex, spanIdHex, traceFlags, traceState, /* remote$=*/ remote); + return ImmutableSpanContext.create( + traceIdHex, spanIdHex, traceFlags, traceState, /* remote=*/ false); } /** @@ -66,31 +58,25 @@ private static SpanContext create( * @param traceState the trace state for the span context. * @return a new {@code SpanContext} with the given identifiers and options. */ - public static SpanContext createFromRemoteParent( + static SpanContext createFromRemoteParent( String traceIdHex, String spanIdHex, byte traceFlags, TraceState traceState) { - return create(traceIdHex, spanIdHex, traceFlags, traceState, /* remote=*/ true); + return ImmutableSpanContext.create( + traceIdHex, spanIdHex, traceFlags, traceState, /* remote=*/ true); } - abstract String getTraceIdHex(); - - abstract String getSpanIdHex(); - /** * Returns the trace identifier associated with this {@code SpanContext}. * * @return the trace identifier associated with this {@code SpanContext}. */ - public String getTraceIdAsHexString() { - return getTraceIdHex(); - } + String getTraceIdAsHexString(); /** * Returns the byte[] representation of the trace identifier associated with this {@link * SpanContext}. */ - @Memoized - public byte[] getTraceIdBytes() { - return TraceId.bytesFromHex(getTraceIdHex(), 0); + default byte[] getTraceIdBytes() { + return TraceId.bytesFromHex(getTraceIdAsHexString(), 0); } /** @@ -98,28 +84,25 @@ public byte[] getTraceIdBytes() { * * @return the span identifier associated with this {@code SpanContext}. */ - public String getSpanIdAsHexString() { - return getSpanIdHex(); - } + String getSpanIdAsHexString(); /** * Returns the byte[] representation of the span identifier associated with this {@link * SpanContext}. */ - @Memoized - public byte[] getSpanIdBytes() { - return SpanId.bytesFromHex(getSpanIdHex(), 0); + default byte[] getSpanIdBytes() { + return SpanId.bytesFromHex(getSpanIdAsHexString(), 0); } /** Whether the span in this context is sampled. */ - public boolean isSampled() { + default boolean isSampled() { return (getTraceFlags() & 1) == 1; } /** The byte-representation of {@link TraceFlags}. */ - public abstract byte getTraceFlags(); + byte getTraceFlags(); - public void copyTraceFlagsHexTo(char[] dest, int destOffset) { + default void copyTraceFlagsHexTo(char[] dest, int destOffset) { BigendianEncoding.byteToBase16String(getTraceFlags(), dest, destOffset); } @@ -128,16 +111,15 @@ public void copyTraceFlagsHexTo(char[] dest, int destOffset) { * * @return the {@code TraceState} associated with this {@code SpanContext}. */ - public abstract TraceState getTraceState(); + TraceState getTraceState(); /** * Returns {@code true} if this {@code SpanContext} is valid. * * @return {@code true} if this {@code SpanContext} is valid. */ - @Memoized - public boolean isValid() { - return TraceId.isValid(getTraceIdHex()) && SpanId.isValid(getSpanIdHex()); + default boolean isValid() { + return TraceId.isValid(getTraceIdAsHexString()) && SpanId.isValid(getSpanIdAsHexString()); } /** @@ -145,5 +127,5 @@ public boolean isValid() { * * @return {@code true} if the {@code SpanContext} was propagated from a remote parent. */ - public abstract boolean isRemote(); + boolean isRemote(); }