diff --git a/api/src/main/java/io/opentelemetry/trace/propagation/BinaryTraceContext.java b/api/src/main/java/io/opentelemetry/trace/propagation/BinaryTraceContext.java index 2c348634336..99e158fb3e6 100644 --- a/api/src/main/java/io/opentelemetry/trace/propagation/BinaryTraceContext.java +++ b/api/src/main/java/io/opentelemetry/trace/propagation/BinaryTraceContext.java @@ -93,6 +93,12 @@ public final class BinaryTraceContext implements BinaryFormat { private static final int ALL_FORMAT_LENGTH = REQUIRED_FORMAT_LENGTH + ID_SIZE + TraceFlags.getSize(); + private static final BinaryTraceContext INSTANCE = new BinaryTraceContext(); + + public static BinaryTraceContext getInstance() { + return INSTANCE; + } + @Override public byte[] toByteArray(SpanContext spanContext) { Utils.checkNotNull(spanContext, "spanContext"); diff --git a/api/src/main/java/io/opentelemetry/trace/propagation/HttpTraceContext.java b/api/src/main/java/io/opentelemetry/trace/propagation/HttpTraceContext.java index 669df7c3280..4f3ca3ae7d7 100644 --- a/api/src/main/java/io/opentelemetry/trace/propagation/HttpTraceContext.java +++ b/api/src/main/java/io/opentelemetry/trace/propagation/HttpTraceContext.java @@ -63,6 +63,12 @@ public class HttpTraceContext implements HttpTextFormat { private static final Pattern TRACESTATE_ENTRY_DELIMITER_SPLIT_PATTERN = Pattern.compile("[ \t]*" + TRACESTATE_ENTRY_DELIMITER + "[ \t]*"); + private static final HttpTraceContext INSTANCE = new HttpTraceContext(); + + public static HttpTraceContext getInstance() { + return INSTANCE; + } + @Override public List fields() { return FIELDS; diff --git a/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdk.java b/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdk.java index 93683dc2a29..3d3240f73a4 100644 --- a/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdk.java +++ b/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdk.java @@ -24,14 +24,10 @@ import io.opentelemetry.trace.Span; import io.opentelemetry.trace.SpanContext; import io.opentelemetry.trace.Tracer; -import io.opentelemetry.trace.propagation.BinaryTraceContext; -import io.opentelemetry.trace.propagation.HttpTraceContext; import io.opentelemetry.trace.unsafe.ContextUtils; /** {@link TracerSdk} is SDK implementation of {@link Tracer}. */ public final class TracerSdk implements Tracer { - private static final BinaryFormat BINARY_FORMAT = new BinaryTraceContext(); - private static final HttpTextFormat HTTP_TEXT_FORMAT = new HttpTraceContext(); private final TracerSharedState sharedState; private final InstrumentationLibraryInfo instrumentationLibraryInfo; @@ -67,12 +63,12 @@ public Span.Builder spanBuilder(String spanName) { @Override public BinaryFormat getBinaryFormat() { - return BINARY_FORMAT; + return sharedState.getBinaryFormat(); } @Override public HttpTextFormat getHttpTextFormat() { - return HTTP_TEXT_FORMAT; + return sharedState.getTextFormat(); } /** diff --git a/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdkProvider.java b/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdkProvider.java index a0bf887a48e..80fb4dbf533 100644 --- a/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdkProvider.java +++ b/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdkProvider.java @@ -16,6 +16,8 @@ package io.opentelemetry.sdk.trace; +import io.opentelemetry.context.propagation.BinaryFormat; +import io.opentelemetry.context.propagation.HttpTextFormat; import io.opentelemetry.internal.Utils; import io.opentelemetry.sdk.common.Clock; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; @@ -24,8 +26,11 @@ import io.opentelemetry.sdk.resources.EnvVarResource; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.config.TraceConfig; +import io.opentelemetry.trace.SpanContext; import io.opentelemetry.trace.Tracer; import io.opentelemetry.trace.TracerProvider; +import io.opentelemetry.trace.propagation.BinaryTraceContext; +import io.opentelemetry.trace.propagation.HttpTraceContext; import java.util.logging.Level; import java.util.logging.Logger; @@ -50,8 +55,14 @@ public static Builder builder() { return new Builder(); } - private TracerSdkProvider(Clock clock, IdsGenerator idsGenerator, Resource resource) { - this.sharedState = new TracerSharedState(clock, idsGenerator, resource); + private TracerSdkProvider( + Clock clock, + IdsGenerator idsGenerator, + Resource resource, + HttpTextFormat textFormat, + BinaryFormat binaryFormat) { + this.sharedState = + new TracerSharedState(clock, idsGenerator, resource, textFormat, binaryFormat); this.tracerSdkComponentRegistry = new TracerSdkComponentRegistry(sharedState); } @@ -124,6 +135,8 @@ public static class Builder { private Clock clock = MillisClock.getInstance(); private IdsGenerator idsGenerator = new RandomIdsGenerator(); private Resource resource = EnvVarResource.getResource(); + private HttpTextFormat textFormat = HttpTraceContext.getInstance(); + private BinaryFormat binaryFormat = BinaryTraceContext.getInstance(); /** * Assign a {@link Clock}. @@ -163,12 +176,36 @@ public Builder setResource(Resource resource) { } /** - * Create a new TracerSdkFactory instance. + * Assign an {@link HttpTextFormat}. * - * @return An initialized TracerSdkFactory. + * @param textFormat The text format to use for propagation. + * @return this + */ + public Builder setTextFormat(HttpTextFormat textFormat) { + Utils.checkNotNull(textFormat, "textFormat"); + this.textFormat = textFormat; + return this; + } + + /** + * Assign a {@link BinaryFormat}. + * + * @param binaryFormat The binary format to use for propagation. + * @return this + */ + public Builder setBinaryFormat(BinaryFormat binaryFormat) { + Utils.checkNotNull(binaryFormat, "binaryFormat"); + this.binaryFormat = binaryFormat; + return this; + } + + /** + * Create a new TracerSdkProvider instance. + * + * @return An initialized TracerSdkProvider. */ public TracerSdkProvider build() { - return new TracerSdkProvider(clock, idsGenerator, resource); + return new TracerSdkProvider(clock, idsGenerator, resource, textFormat, binaryFormat); } private Builder() {} diff --git a/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSharedState.java b/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSharedState.java index fc80f00ec40..0f063ffd4bf 100644 --- a/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSharedState.java +++ b/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSharedState.java @@ -16,9 +16,12 @@ package io.opentelemetry.sdk.trace; +import io.opentelemetry.context.propagation.BinaryFormat; +import io.opentelemetry.context.propagation.HttpTextFormat; import io.opentelemetry.sdk.common.Clock; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.config.TraceConfig; +import io.opentelemetry.trace.SpanContext; import java.util.ArrayList; import java.util.List; import javax.annotation.concurrent.GuardedBy; @@ -29,6 +32,8 @@ final class TracerSharedState { private final Clock clock; private final IdsGenerator idsGenerator; private final Resource resource; + private final HttpTextFormat textFormat; + private final BinaryFormat binaryFormat; // Reads and writes are atomic for reference variables. Use volatile to ensure that these // operations are visible on other CPUs as well. @@ -39,10 +44,17 @@ final class TracerSharedState { @GuardedBy("lock") private final List registeredSpanProcessors = new ArrayList<>(); - TracerSharedState(Clock clock, IdsGenerator idsGenerator, Resource resource) { + TracerSharedState( + Clock clock, + IdsGenerator idsGenerator, + Resource resource, + HttpTextFormat textFormat, + BinaryFormat binaryFormat) { this.clock = clock; this.idsGenerator = idsGenerator; this.resource = resource; + this.textFormat = textFormat; + this.binaryFormat = binaryFormat; } Clock getClock() { @@ -57,6 +69,10 @@ Resource getResource() { return resource; } + HttpTextFormat getTextFormat() { + return textFormat; + } + /** * Returns the active {@code TraceConfig}. * @@ -117,4 +133,8 @@ void stop() { isStopped = true; } } + + public BinaryFormat getBinaryFormat() { + return binaryFormat; + } } diff --git a/sdk/src/test/java/io/opentelemetry/sdk/trace/TracerSdkProviderTest.java b/sdk/src/test/java/io/opentelemetry/sdk/trace/TracerSdkProviderTest.java index 28d7b532bdf..e0c06477966 100644 --- a/sdk/src/test/java/io/opentelemetry/sdk/trace/TracerSdkProviderTest.java +++ b/sdk/src/test/java/io/opentelemetry/sdk/trace/TracerSdkProviderTest.java @@ -19,12 +19,15 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; +import io.opentelemetry.context.propagation.BinaryFormat; +import io.opentelemetry.context.propagation.HttpTextFormat; import io.opentelemetry.sdk.common.Clock; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.config.TraceConfig; import io.opentelemetry.trace.DefaultSpan; import io.opentelemetry.trace.Span; +import io.opentelemetry.trace.SpanContext; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -80,6 +83,36 @@ public void builder_NullIdsGenerator() { TracerSdkProvider.builder().setIdsGenerator(null); } + @Test + public void builder_NullTextFormat() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("textFormat"); + TracerSdkProvider.builder().setTextFormat(null); + } + + @Test + public void builder_NullBinaryFormat() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("binaryFormat"); + TracerSdkProvider.builder().setBinaryFormat(null); + } + + @Test + public void builder_setTextFormat() { + @SuppressWarnings("unchecked") + final HttpTextFormat format = Mockito.mock(HttpTextFormat.class); + final TracerSdkProvider registry = TracerSdkProvider.builder().setTextFormat(format).build(); + assertThat(registry.get("test").getHttpTextFormat()).isSameInstanceAs(format); + } + + @Test + public void builder_setBinaryFormat() { + @SuppressWarnings("unchecked") + final BinaryFormat format = Mockito.mock(BinaryFormat.class); + final TracerSdkProvider registry = TracerSdkProvider.builder().setBinaryFormat(format).build(); + assertThat(registry.get("test").getBinaryFormat()).isSameInstanceAs(format); + } + @Test public void defaultGet() { assertThat(tracerFactory.get("test")).isInstanceOf(TracerSdk.class);