From 690651b65a938c903c35d65aef3182999fcb1b19 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Fri, 20 Mar 2020 21:38:05 +0100 Subject: [PATCH] Context propagation update (OTEP 66) (#720) * Initial Propagators refactor. * Add tests for the new propagators changes. * Make the SDK compile/pass. * Make the OT shim compile/pass. * Make contrib components compile/pass. * Improvement over Span/SpanContext handling in Context. * Add Span.setParent(Context) overload. * Do not provide default values for Span/SpanContext keys in Context. * Improve the Context's active state handling. * Rename DistributedContext to CorrelationContext. * Improve names for correlationcontext's ContextUtils methods. * Don't provide an automatic default for current CorrelationContext. * Improve the client-server example after the recent changes. * Adds CorrelationContext.Builder.setParent(Context) overload. * s/be/become. * Fix javadoc. * No need to use diamond. * Simply import withScopedContext(). * Fix the API/SDK build. * Remove the builder from the Propagators interface. * Fix name. * Use Collections.emptyList() directly. * Rename Propagators to ContextPropagators. * Move context/ members in api/ to context_prop/ * Add check/tests for null scoped Contexts. * Rename ContextUtils classes to better alternatives. * Update the context* util classes. * Make the code compile after the latest master merge. * Cache the fields() in our default composite propagator. * Remove the overloads of setParent(Context) for now. * Use DefaultSpan for the tests instead of calling getTracerProvider() * Fix the sdk testbed artifact build. * Make the B3 propagator comply with the new propagator API. * Simplify the HttpTraceContextTest tests. * Simplify the ContextUtils* classes handling of default values. * Minor nit. * Update api/src/main/java/io/opentelemetry/OpenTelemetry.java Co-Authored-By: Giovanni Liva * Annotate ContextPropagators with ThreadSafe instead of Immutable. * Do not use the fully qualified ContextUtils identifier. * Remove SpanContext support from TracingContextUtils. * Rever to using non-defaulted key for TracingContextUtils. * Revert the default keys for CorrelationsContextUtils. Co-authored-by: Giovanni Liva --- .../HttpTraceContextExtractBenchmark.java | 9 +- .../HttpTraceContextInjectBenchmark.java | 7 +- .../java/io/opentelemetry/OpenTelemetry.java | 36 ++++ .../CorrelationContextManager.java | 50 ------ .../DefaultCorrelationContextManager.java | 36 +--- .../io/opentelemetry/trace/DefaultTracer.java | 23 +-- .../java/io/opentelemetry/trace/Tracer.java | 57 ------ .../trace/propagation/B3Propagator.java | 26 ++- .../trace/propagation/HttpTraceContext.java | 30 +++- .../io/opentelemetry/OpenTelemetryTest.java | 31 ++-- .../trace/DefaultTracerTest.java | 21 ++- .../trace/propagation/B3PropagatorTest.java | 96 ++++++---- .../propagation/HttpTraceContextTest.java | 97 ++++++---- .../propagation/ContextPropagators.java | 94 ++++++++++ .../DefaultContextPropagators.java | 166 ++++++++++++++++++ .../context/propagation/HttpTextFormat.java | 39 ++-- .../propagation/DefaultPropagatorsTest.java | 162 +++++++++++++++++ .../opentracingshim/BaseShimObject.java | 5 + .../opentracingshim/Propagation.java | 34 ++-- .../opentracingshim/TelemetryInfo.java | 10 +- .../opentracingshim/TraceShim.java | 6 +- .../opentracingshim/SpanBuilderShimTest.java | 3 +- .../opentracingshim/SpanShimTest.java | 3 +- .../opentracingshim/TracerShimTest.java | 3 +- .../CorrelationContextManagerSdk.java | 8 - .../sdk/trace/SpanBuilderSdk.java | 14 +- .../io/opentelemetry/sdk/trace/TracerSdk.java | 9 - .../sdk/trace/TracerSdkTest.java | 6 - .../trace/testbed/clientserver/Client.java | 6 +- .../trace/testbed/clientserver/Server.java | 11 +- 30 files changed, 774 insertions(+), 324 deletions(-) create mode 100644 context_prop/src/main/java/io/opentelemetry/context/propagation/ContextPropagators.java create mode 100644 context_prop/src/main/java/io/opentelemetry/context/propagation/DefaultContextPropagators.java create mode 100644 context_prop/src/test/java/io/opentelemetry/context/propagation/DefaultPropagatorsTest.java diff --git a/api/src/jmh/java/io/opentelemetry/trace/propagation/HttpTraceContextExtractBenchmark.java b/api/src/jmh/java/io/opentelemetry/trace/propagation/HttpTraceContextExtractBenchmark.java index 5dc9c88e608..0f53caf57e0 100644 --- a/api/src/jmh/java/io/opentelemetry/trace/propagation/HttpTraceContextExtractBenchmark.java +++ b/api/src/jmh/java/io/opentelemetry/trace/propagation/HttpTraceContextExtractBenchmark.java @@ -16,8 +16,10 @@ package io.opentelemetry.trace.propagation; +import io.grpc.Context; import io.opentelemetry.context.propagation.HttpTextFormat.Getter; -import io.opentelemetry.trace.SpanContext; +import io.opentelemetry.trace.Span; +import io.opentelemetry.trace.TracingContextUtils; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -69,8 +71,9 @@ public void setup() { @Measurement(iterations = 15, time = 1) @OutputTimeUnit(TimeUnit.NANOSECONDS) @Warmup(iterations = 5, time = 1) - public SpanContext measureExtract() { - return httpTraceContext.extract(carrier, getter); + public Span measureExtract() { + return TracingContextUtils.getSpan( + httpTraceContext.extract(Context.current(), carrier, getter)); } @TearDown(Level.Iteration) diff --git a/api/src/jmh/java/io/opentelemetry/trace/propagation/HttpTraceContextInjectBenchmark.java b/api/src/jmh/java/io/opentelemetry/trace/propagation/HttpTraceContextInjectBenchmark.java index b069140efbd..733d1ac9af3 100644 --- a/api/src/jmh/java/io/opentelemetry/trace/propagation/HttpTraceContextInjectBenchmark.java +++ b/api/src/jmh/java/io/opentelemetry/trace/propagation/HttpTraceContextInjectBenchmark.java @@ -16,12 +16,15 @@ package io.opentelemetry.trace.propagation; +import io.grpc.Context; import io.opentelemetry.context.propagation.HttpTextFormat.Setter; +import io.opentelemetry.trace.DefaultSpan; import io.opentelemetry.trace.SpanContext; import io.opentelemetry.trace.SpanId; import io.opentelemetry.trace.TraceFlags; import io.opentelemetry.trace.TraceId; import io.opentelemetry.trace.TraceState; +import io.opentelemetry.trace.TracingContextUtils; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -69,7 +72,9 @@ public void set(Map carrier, String key, String value) { @OutputTimeUnit(TimeUnit.NANOSECONDS) @Warmup(iterations = 5, time = 1) public Map measureInject() { - httpTraceContext.inject(contextToTest, carrier, setter); + Context context = + TracingContextUtils.withSpan(DefaultSpan.create(contextToTest), Context.current()); + httpTraceContext.inject(context, carrier, setter); return carrier; } diff --git a/api/src/main/java/io/opentelemetry/OpenTelemetry.java b/api/src/main/java/io/opentelemetry/OpenTelemetry.java index be52fc9468b..1071bf36741 100644 --- a/api/src/main/java/io/opentelemetry/OpenTelemetry.java +++ b/api/src/main/java/io/opentelemetry/OpenTelemetry.java @@ -16,10 +16,13 @@ package io.opentelemetry; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.context.propagation.DefaultContextPropagators; import io.opentelemetry.correlationcontext.CorrelationContextManager; import io.opentelemetry.correlationcontext.DefaultCorrelationContextManager; import io.opentelemetry.correlationcontext.DefaultCorrelationContextManagerProvider; import io.opentelemetry.correlationcontext.spi.CorrelationContextManagerProvider; +import io.opentelemetry.internal.Utils; import io.opentelemetry.metrics.DefaultMeterProvider; import io.opentelemetry.metrics.DefaultMetricsProvider; import io.opentelemetry.metrics.Meter; @@ -29,6 +32,7 @@ import io.opentelemetry.trace.DefaultTracerProvider; import io.opentelemetry.trace.Tracer; import io.opentelemetry.trace.TracerProvider; +import io.opentelemetry.trace.propagation.HttpTraceContext; import io.opentelemetry.trace.spi.TraceProvider; import java.util.ServiceLoader; import javax.annotation.Nullable; @@ -53,6 +57,9 @@ public final class OpenTelemetry { private final MeterProvider meterProvider; private final CorrelationContextManager contextManager; + private volatile ContextPropagators propagators = + DefaultContextPropagators.builder().addHttpTextFormat(new HttpTraceContext()).build(); + /** * Returns a singleton {@link TracerProvider}. * @@ -90,6 +97,35 @@ public static CorrelationContextManager getCorrelationContextManager() { return getInstance().contextManager; } + /** + * Returns a {@link ContextPropagators} object, which can be used to access the set of registered + * propagators for each supported format. + * + * @return registered propagators container, defaulting to a {@link ContextPropagators} object + * with {@link HttpTraceContext} registered. + * @throws IllegalStateException if a specified manager (via system properties) could not be + * found. + * @since 0.3.0 + */ + public static ContextPropagators getPropagators() { + return getInstance().propagators; + } + + /** + * Sets the {@link ContextPropagators} object, which can be used to access the set of registered + * propagators for each supported format. + * + * @param propagators the {@link ContextPropagators} object to be registered. + * @throws IllegalStateException if a specified manager (via system properties) could not be + * found. + * @throws NullPointerException if {@code propagators} is {@code null}. + * @since 0.3.0 + */ + public static void setPropagators(ContextPropagators propagators) { + Utils.checkNotNull(propagators, "propagators"); + getInstance().propagators = propagators; + } + /** Lazy loads an instance. */ private static OpenTelemetry getInstance() { if (instance == null) { diff --git a/api/src/main/java/io/opentelemetry/correlationcontext/CorrelationContextManager.java b/api/src/main/java/io/opentelemetry/correlationcontext/CorrelationContextManager.java index e9a43195245..be1285d6f6c 100644 --- a/api/src/main/java/io/opentelemetry/correlationcontext/CorrelationContextManager.java +++ b/api/src/main/java/io/opentelemetry/correlationcontext/CorrelationContextManager.java @@ -17,7 +17,6 @@ package io.opentelemetry.correlationcontext; import io.opentelemetry.context.Scope; -import io.opentelemetry.context.propagation.HttpTextFormat; import javax.annotation.concurrent.ThreadSafe; /** @@ -63,53 +62,4 @@ public interface CorrelationContextManager { * @since 0.1.0 */ Scope withContext(CorrelationContext distContext); - - /** - * Returns the {@link HttpTextFormat} for this implementation. - * - *

Usually this will be the W3C Correlation Context as the HTTP text format. For more details, - * see correlation-context. - * - *

Example of usage on the client: - * - *

{@code
-   * private static final CorrelationContextManager contextManager =
-   *     OpenTelemetry.getCorrelationContextManager();
-   * private static final HttpTextFormat textFormat = contextManager.getHttpTextFormat();
-   *
-   * private static final HttpTextFormat.Setter setter =
-   *     new HttpTextFormat.Setter() {
-   *       public void put(HttpURLConnection carrier, String key, String value) {
-   *         carrier.setRequestProperty(field, value);
-   *       }
-   *     };
-   *
-   * void makeHttpRequest() {
-   *   HttpURLConnection connection =
-   *       (HttpURLConnection) new URL("http://myserver").openConnection();
-   *   textFormat.inject(contextManager.getCurrentContext(), connection, httpURLConnectionSetter);
-   *   // Send the request, wait for response and maybe set the status if not ok.
-   * }
-   * }
- * - *

Example of usage on the server: - * - *

{@code
-   * private static final CorrelationContextManager contextManager =
-   *     OpenTelemetry.getCorrelationContextManager();
-   * private static final HttpTextFormat textFormat = contextManager.getHttpTextFormat();
-   * private static final HttpTextFormat.Getter getter = ...;
-   *
-   * void onRequestReceived(HttpRequest request) {
-   *   CorrelationContext distContext = textFormat.extract(request, getter);
-   *   try (Scope s = contextManager.withContext(distContext)) {
-   *     // Handle request and send response back.
-   *   }
-   * }
-   * }
- * - * @return the {@code HttpTextFormat} for this implementation. - * @since 0.1.0 - */ - HttpTextFormat getHttpTextFormat(); } diff --git a/api/src/main/java/io/opentelemetry/correlationcontext/DefaultCorrelationContextManager.java b/api/src/main/java/io/opentelemetry/correlationcontext/DefaultCorrelationContextManager.java index 9fc7b5e0dea..8d47920faf1 100644 --- a/api/src/main/java/io/opentelemetry/correlationcontext/DefaultCorrelationContextManager.java +++ b/api/src/main/java/io/opentelemetry/correlationcontext/DefaultCorrelationContextManager.java @@ -17,10 +17,7 @@ package io.opentelemetry.correlationcontext; import io.opentelemetry.context.Scope; -import io.opentelemetry.context.propagation.HttpTextFormat; import io.opentelemetry.internal.Utils; -import java.util.Collections; -import java.util.List; import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; @@ -33,8 +30,6 @@ public final class DefaultCorrelationContextManager implements CorrelationContextManager { private static final DefaultCorrelationContextManager INSTANCE = new DefaultCorrelationContextManager(); - private static final HttpTextFormat HTTP_TEXT_FORMAT = - new NoopHttpTextFormat(); /** * Returns a {@code CorrelationContextManager} singleton that is the default implementation for @@ -62,11 +57,6 @@ public Scope withContext(CorrelationContext distContext) { return CorrelationsContextUtils.currentContextWith(distContext); } - @Override - public HttpTextFormat getHttpTextFormat() { - return HTTP_TEXT_FORMAT; - } - @Immutable private static final class NoopCorrelationContextBuilder implements CorrelationContext.Builder { @Override @@ -82,10 +72,10 @@ public CorrelationContext.Builder setNoParent() { @Override public CorrelationContext.Builder put( - EntryKey key, EntryValue value, EntryMetadata tagMetadata) { + EntryKey key, EntryValue value, EntryMetadata entryMetadata) { Utils.checkNotNull(key, "key"); Utils.checkNotNull(value, "value"); - Utils.checkNotNull(tagMetadata, "tagMetadata"); + Utils.checkNotNull(entryMetadata, "entryMetadata"); return this; } @@ -100,26 +90,4 @@ public CorrelationContext build() { return EmptyCorrelationContext.getInstance(); } } - - @Immutable - private static final class NoopHttpTextFormat implements HttpTextFormat { - @Override - public List fields() { - return Collections.emptyList(); - } - - @Override - public void inject(CorrelationContext distContext, C carrier, Setter setter) { - Utils.checkNotNull(distContext, "distContext"); - Utils.checkNotNull(carrier, "carrier"); - Utils.checkNotNull(setter, "setter"); - } - - @Override - public CorrelationContext extract(C carrier, Getter getter) { - Utils.checkNotNull(carrier, "carrier"); - Utils.checkNotNull(getter, "getter"); - return EmptyCorrelationContext.getInstance(); - } - } } diff --git a/api/src/main/java/io/opentelemetry/trace/DefaultTracer.java b/api/src/main/java/io/opentelemetry/trace/DefaultTracer.java index c8259578d24..8b2d94df6d6 100644 --- a/api/src/main/java/io/opentelemetry/trace/DefaultTracer.java +++ b/api/src/main/java/io/opentelemetry/trace/DefaultTracer.java @@ -18,10 +18,9 @@ import io.opentelemetry.common.AttributeValue; import io.opentelemetry.context.Scope; -import io.opentelemetry.context.propagation.HttpTextFormat; import io.opentelemetry.internal.Utils; -import io.opentelemetry.trace.propagation.HttpTraceContext; import java.util.Map; +import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; /** @@ -32,7 +31,6 @@ @ThreadSafe public final class DefaultTracer implements Tracer { private static final DefaultTracer INSTANCE = new DefaultTracer(); - private static final HttpTextFormat HTTP_TEXT_FORMAT = new HttpTraceContext(); /** * Returns a {@code Tracer} singleton that is the default implementations for {@link Tracer}. @@ -56,30 +54,24 @@ public Scope withSpan(Span span) { @Override public Span.Builder spanBuilder(String spanName) { - return NoopSpanBuilder.create(this, spanName); - } - - @Override - public HttpTextFormat getHttpTextFormat() { - return HTTP_TEXT_FORMAT; + return NoopSpanBuilder.create(spanName); } private DefaultTracer() {} // Noop implementation of Span.Builder. private static final class NoopSpanBuilder implements Span.Builder { - static NoopSpanBuilder create(Tracer tracer, String spanName) { - return new NoopSpanBuilder(tracer, spanName); + static NoopSpanBuilder create(String spanName) { + return new NoopSpanBuilder(spanName); } - private final Tracer tracer; private boolean isRootSpan; - private SpanContext spanContext; + @Nullable private SpanContext spanContext; @Override public Span startSpan() { if (spanContext == null && !isRootSpan) { - spanContext = tracer.getCurrentSpan().getContext(); + spanContext = TracingContextUtils.getCurrentSpan().getContext(); } return spanContext != null && !SpanContext.getInvalid().equals(spanContext) @@ -165,9 +157,8 @@ public NoopSpanBuilder setStartTimestamp(long startTimestamp) { return this; } - private NoopSpanBuilder(Tracer tracer, String name) { + private NoopSpanBuilder(String name) { Utils.checkNotNull(name, "name"); - this.tracer = tracer; } } } diff --git a/api/src/main/java/io/opentelemetry/trace/Tracer.java b/api/src/main/java/io/opentelemetry/trace/Tracer.java index 703cc3c2adf..cb02053181c 100644 --- a/api/src/main/java/io/opentelemetry/trace/Tracer.java +++ b/api/src/main/java/io/opentelemetry/trace/Tracer.java @@ -18,8 +18,6 @@ import com.google.errorprone.annotations.MustBeClosed; import io.opentelemetry.context.Scope; -import io.opentelemetry.context.propagation.HttpTextFormat; -import io.opentelemetry.trace.propagation.HttpTraceContext; import javax.annotation.concurrent.ThreadSafe; /** @@ -152,59 +150,4 @@ public interface Tracer { * @since 0.1.0 */ Span.Builder spanBuilder(String spanName); - - /** - * Returns the {@link HttpTextFormat} for this tracer implementation. - * - *

If no tracer implementation is provided, this defaults to the W3C Trace Context HTTP text - * format ({@link HttpTraceContext}). For more details see W3C Trace Context. - * - *

Example of usage on the client: - * - *

{@code
-   * private static final Tracer tracer = OpenTelemetry.getTracer();
-   * private static final HttpTextFormat textFormat = tracer.getHttpTextFormat();
-   * private static final HttpTextFormat.Setter setter =
-   *         new HttpTextFormat.Setter() {
-   *   public void put(HttpURLConnection carrier, String key, String value) {
-   *     carrier.setRequestProperty(field, value);
-   *   }
-   * }
-   *
-   * void makeHttpRequest() {
-   *   Span span = tracer.spanBuilder("MyRequest").setSpanKind(Span.Kind.CLIENT).startSpan();
-   *   try (Scope s = tracer.withSpan(span)) {
-   *     HttpURLConnection connection =
-   *         (HttpURLConnection) new URL("http://myserver").openConnection();
-   *     textFormat.inject(span.getContext(), connection, httpURLConnectionSetter);
-   *     // Send the request, wait for response and maybe set the status if not ok.
-   *   }
-   *   span.end();  // Can set a status.
-   * }
-   * }
- * - *

Example of usage on the server: - * - *

{@code
-   * private static final Tracer tracer = OpenTelemetry.getTracer();
-   * private static final HttpTextFormat textFormat = tracer.getHttpTextFormat();
-   * private static final HttpTextFormat.Getter getter = ...;
-   *
-   * void onRequestReceived(HttpRequest request) {
-   *   SpanContext spanContext = textFormat.extract(request, getter);
-   *   Span span = tracer.spanBuilder("MyRequest")
-   *       .setParent(spanContext)
-   *       .setSpanKind(Span.Kind.SERVER).startSpan();
-   *   try (Scope s = tracer.withSpan(span)) {
-   *     // Handle request and send response back.
-   *   }
-   *   span.end()
-   * }
-   * }
- * - * @return the {@code HttpTextFormat} for this implementation. - * @since 0.1.0 - */ - HttpTextFormat getHttpTextFormat(); } diff --git a/api/src/main/java/io/opentelemetry/trace/propagation/B3Propagator.java b/api/src/main/java/io/opentelemetry/trace/propagation/B3Propagator.java index d3f7efa4bc0..11550bf6338 100644 --- a/api/src/main/java/io/opentelemetry/trace/propagation/B3Propagator.java +++ b/api/src/main/java/io/opentelemetry/trace/propagation/B3Propagator.java @@ -18,13 +18,17 @@ import static io.opentelemetry.internal.Utils.checkNotNull; +import io.grpc.Context; import io.opentelemetry.context.propagation.HttpTextFormat; import io.opentelemetry.internal.StringUtils; +import io.opentelemetry.trace.DefaultSpan; +import io.opentelemetry.trace.Span; import io.opentelemetry.trace.SpanContext; import io.opentelemetry.trace.SpanId; import io.opentelemetry.trace.TraceFlags; import io.opentelemetry.trace.TraceId; import io.opentelemetry.trace.TraceState; +import io.opentelemetry.trace.TracingContextUtils; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -37,7 +41,7 @@ * href=https://github.com/openzipkin/b3-propagation>openzipkin/b3-propagation. */ @Immutable -public class B3Propagator implements HttpTextFormat { +public class B3Propagator implements HttpTextFormat { private static final Logger logger = Logger.getLogger(HttpTraceContext.class.getName()); static final String TRACE_ID_HEADER = "X-B3-TraceId"; @@ -79,11 +83,17 @@ public List fields() { } @Override - public void inject(SpanContext spanContext, C carrier, Setter setter) { - checkNotNull(spanContext, "spanContext"); + public void inject(Context context, C carrier, Setter setter) { + checkNotNull(context, "context"); checkNotNull(setter, "setter"); checkNotNull(carrier, "carrier"); + Span span = TracingContextUtils.getSpanWithoutDefault(context); + if (span == null) { + return; + } + + SpanContext spanContext = span.getContext(); String sampled = spanContext.getTraceFlags().isSampled() ? TRUE_INT : FALSE_INT; if (singleHeader) { @@ -103,15 +113,19 @@ public void inject(SpanContext spanContext, C carrier, Setter setter) { } @Override - public SpanContext extract(C carrier, Getter getter) { + public Context extract(Context context, C carrier, Getter getter) { checkNotNull(carrier, "carrier"); checkNotNull(getter, "getter"); + SpanContext spanContext = null; + if (singleHeader) { - return getSpanContextFromSingleHeader(carrier, getter); + spanContext = getSpanContextFromSingleHeader(carrier, getter); } else { - return getSpanContextFromMultipleHeaders(carrier, getter); + spanContext = getSpanContextFromMultipleHeaders(carrier, getter); } + + return TracingContextUtils.withSpan(DefaultSpan.create(spanContext), context); } @SuppressWarnings("StringSplitter") 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 13854741bdd..4468b6f755d 100644 --- a/api/src/main/java/io/opentelemetry/trace/propagation/HttpTraceContext.java +++ b/api/src/main/java/io/opentelemetry/trace/propagation/HttpTraceContext.java @@ -19,12 +19,16 @@ import static io.opentelemetry.internal.Utils.checkArgument; import static io.opentelemetry.internal.Utils.checkNotNull; +import io.grpc.Context; import io.opentelemetry.context.propagation.HttpTextFormat; +import io.opentelemetry.trace.DefaultSpan; +import io.opentelemetry.trace.Span; import io.opentelemetry.trace.SpanContext; import io.opentelemetry.trace.SpanId; import io.opentelemetry.trace.TraceFlags; import io.opentelemetry.trace.TraceId; import io.opentelemetry.trace.TraceState; +import io.opentelemetry.trace.TracingContextUtils; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -37,7 +41,7 @@ * href=https://github.com/w3c/distributed-tracing>w3c/distributed-tracing. */ @Immutable -public class HttpTraceContext implements HttpTextFormat { +public class HttpTraceContext implements HttpTextFormat { private static final Logger logger = Logger.getLogger(HttpTraceContext.class.getName()); private static final TraceState TRACE_STATE_DEFAULT = TraceState.builder().build(); @@ -72,10 +76,20 @@ public List fields() { } @Override - public void inject(SpanContext spanContext, C carrier, Setter setter) { - checkNotNull(spanContext, "spanContext"); + public void inject(Context context, C carrier, Setter setter) { + checkNotNull(context, "context"); checkNotNull(setter, "setter"); checkNotNull(carrier, "carrier"); + + Span span = TracingContextUtils.getSpanWithoutDefault(context); + if (span == null) { + return; + } + + injectImpl(span.getContext(), carrier, setter); + } + + private static void injectImpl(SpanContext spanContext, C carrier, Setter setter) { char[] chars = new char[TRACEPARENT_HEADER_SIZE]; chars[0] = VERSION.charAt(0); chars[1] = VERSION.charAt(1); @@ -105,9 +119,17 @@ public void inject(SpanContext spanContext, C carrier, Setter setter) { } @Override - public >> extends @NonNull Object*/> SpanContext extract(C carrier, Getter getter) { + public >> extends @NonNull Object*/> Context extract( + Context context, C carrier, Getter getter) { + checkNotNull(carrier, "context"); checkNotNull(carrier, "carrier"); checkNotNull(getter, "getter"); + + SpanContext spanContext = extractImpl(carrier, getter); + return TracingContextUtils.withSpan(DefaultSpan.create(spanContext), context); + } + + private static SpanContext extractImpl(C carrier, Getter getter) { String traceparent = getter.get(carrier, TRACE_PARENT); if (traceparent == null) { return SpanContext.getInvalid(); diff --git a/api/src/test/java/io/opentelemetry/OpenTelemetryTest.java b/api/src/test/java/io/opentelemetry/OpenTelemetryTest.java index f8ec3b8d740..95692ab3ef1 100644 --- a/api/src/test/java/io/opentelemetry/OpenTelemetryTest.java +++ b/api/src/test/java/io/opentelemetry/OpenTelemetryTest.java @@ -20,7 +20,8 @@ import static org.junit.Assert.assertTrue; import io.opentelemetry.context.Scope; -import io.opentelemetry.context.propagation.HttpTextFormat; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.context.propagation.DefaultContextPropagators; import io.opentelemetry.correlationcontext.CorrelationContext; import io.opentelemetry.correlationcontext.CorrelationContextManager; import io.opentelemetry.correlationcontext.DefaultCorrelationContextManager; @@ -38,7 +39,6 @@ import io.opentelemetry.metrics.spi.MetricsProvider; import io.opentelemetry.trace.DefaultTracerProvider; import io.opentelemetry.trace.Span; -import io.opentelemetry.trace.SpanContext; import io.opentelemetry.trace.Tracer; import io.opentelemetry.trace.TracerProvider; import io.opentelemetry.trace.spi.TraceProvider; @@ -85,6 +85,8 @@ public void testDefault() { .isInstanceOf(DefaultCorrelationContextManager.class); assertThat(OpenTelemetry.getCorrelationContextManager()) .isSameInstanceAs(OpenTelemetry.getCorrelationContextManager()); + assertThat(OpenTelemetry.getPropagators()).isInstanceOf(DefaultContextPropagators.class); + assertThat(OpenTelemetry.getPropagators()).isSameInstanceAs(OpenTelemetry.getPropagators()); } @Test @@ -201,6 +203,19 @@ public void testCorrelationContextManagerNotFound() { OpenTelemetry.getCorrelationContextManager(); } + @Test + public void testPropagatorsSet() { + ContextPropagators propagators = DefaultContextPropagators.builder().build(); + OpenTelemetry.setPropagators(propagators); + assertThat(OpenTelemetry.getPropagators()).isEqualTo(propagators); + } + + @Test + public void testPropagatorsSetNull() { + thrown.expect(NullPointerException.class); + OpenTelemetry.setPropagators(null); + } + private static File createService(Class service, Class... impls) throws IOException { URL location = Tracer.class.getProtectionDomain().getCodeSource().getLocation(); File file = new File(location.getPath() + "META-INF/services/" + service.getName()); @@ -262,12 +277,6 @@ public Span.Builder spanBuilder(String spanName) { return null; } - @Nullable - @Override - public HttpTextFormat getHttpTextFormat() { - return null; - } - @Override public TracerProvider create() { return new FirstTraceProvider(); @@ -381,11 +390,5 @@ public CorrelationContext.Builder contextBuilder() { public Scope withContext(CorrelationContext distContext) { return null; } - - @Nullable - @Override - public HttpTextFormat getHttpTextFormat() { - return null; - } } } diff --git a/api/src/test/java/io/opentelemetry/trace/DefaultTracerTest.java b/api/src/test/java/io/opentelemetry/trace/DefaultTracerTest.java index 605ddc99927..a47fb8d3ed5 100644 --- a/api/src/test/java/io/opentelemetry/trace/DefaultTracerTest.java +++ b/api/src/test/java/io/opentelemetry/trace/DefaultTracerTest.java @@ -18,8 +18,9 @@ import static com.google.common.truth.Truth.assertThat; +import io.grpc.Context; +import io.opentelemetry.context.ContextUtils; import io.opentelemetry.context.Scope; -import io.opentelemetry.trace.propagation.HttpTraceContext; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -73,11 +74,6 @@ public void defaultSpanBuilderWithName() { assertThat(defaultTracer.spanBuilder(SPAN_NAME).startSpan()).isInstanceOf(DefaultSpan.class); } - @Test - public void defaultHttpTextFormat() { - assertThat(defaultTracer.getHttpTextFormat()).isInstanceOf(HttpTraceContext.class); - } - @Test public void testInProcessContext() { Span span = defaultTracer.spanBuilder(SPAN_NAME).startSpan(); @@ -123,4 +119,17 @@ public void testSpanContextPropagationCurrentSpan() { scope.close(); } } + + @Test + public void testSpanContextPropagationCurrentSpanContext() { + Context context = + TracingContextUtils.withSpan(DefaultSpan.create(spanContext), Context.current()); + Scope scope = ContextUtils.withScopedContext(context); + try { + Span span = defaultTracer.spanBuilder(SPAN_NAME).startSpan(); + assertThat(span.getContext()).isSameInstanceAs(spanContext); + } finally { + scope.close(); + } + } } diff --git a/api/src/test/java/io/opentelemetry/trace/propagation/B3PropagatorTest.java b/api/src/test/java/io/opentelemetry/trace/propagation/B3PropagatorTest.java index 059a8add7c6..64832036370 100644 --- a/api/src/test/java/io/opentelemetry/trace/propagation/B3PropagatorTest.java +++ b/api/src/test/java/io/opentelemetry/trace/propagation/B3PropagatorTest.java @@ -18,14 +18,17 @@ import static com.google.common.truth.Truth.assertThat; +import io.grpc.Context; import io.opentelemetry.context.propagation.HttpTextFormat.Getter; import io.opentelemetry.context.propagation.HttpTextFormat.Setter; import io.opentelemetry.internal.StringUtils; +import io.opentelemetry.trace.DefaultSpan; import io.opentelemetry.trace.SpanContext; import io.opentelemetry.trace.SpanId; import io.opentelemetry.trace.TraceFlags; import io.opentelemetry.trace.TraceId; import io.opentelemetry.trace.TraceState; +import io.opentelemetry.trace.TracingContextUtils; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -70,11 +73,21 @@ public String get(Map carrier, String key) { private final B3Propagator b3PropagatorSingleHeader = new B3Propagator(true); @Rule public ExpectedException thrown = ExpectedException.none(); + private static SpanContext getSpanContext(Context context) { + return TracingContextUtils.getSpan(context).getContext(); + } + + private static Context withSpanContext(SpanContext spanContext, Context context) { + return TracingContextUtils.withSpan(DefaultSpan.create(spanContext), context); + } + @Test public void inject_SampledContext() { Map carrier = new LinkedHashMap<>(); b3Propagator.inject( - SpanContext.create(TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT), + withSpanContext( + SpanContext.create(TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT), + Context.current()), carrier, setter); assertThat(carrier).containsEntry(B3Propagator.TRACE_ID_HEADER, TRACE_ID_BASE16); @@ -86,7 +99,9 @@ public void inject_SampledContext() { public void inject_NotSampledContext() { Map carrier = new LinkedHashMap<>(); b3Propagator.inject( - SpanContext.create(TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_DEFAULT), + withSpanContext( + SpanContext.create(TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_DEFAULT), + Context.current()), carrier, setter); assertThat(carrier).containsEntry(B3Propagator.TRACE_ID_HEADER, TRACE_ID_BASE16); @@ -101,7 +116,7 @@ public void extract_SampledContext_Int() { carrier.put(B3Propagator.SPAN_ID_HEADER, SPAN_ID_BASE16); carrier.put(B3Propagator.SAMPLED_HEADER, B3Propagator.TRUE_INT); - assertThat(b3Propagator.extract(carrier, getter)) + assertThat(getSpanContext(b3Propagator.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -114,7 +129,7 @@ public void extract_SampledContext_Bool() { carrier.put(B3Propagator.SPAN_ID_HEADER, SPAN_ID_BASE16); carrier.put(B3Propagator.SAMPLED_HEADER, "true"); - assertThat(b3Propagator.extract(carrier, getter)) + assertThat(getSpanContext(b3Propagator.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -127,7 +142,7 @@ public void extract_NotSampledContext() { carrier.put(B3Propagator.SPAN_ID_HEADER, SPAN_ID_BASE16); carrier.put(B3Propagator.SAMPLED_HEADER, B3Propagator.FALSE_INT); - assertThat(b3Propagator.extract(carrier, getter)) + assertThat(getSpanContext(b3Propagator.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_DEFAULT)); @@ -140,7 +155,7 @@ public void extract_SampledContext_Int_Short_TraceId() { carrier.put(B3Propagator.SPAN_ID_HEADER, SPAN_ID_BASE16); carrier.put(B3Propagator.SAMPLED_HEADER, B3Propagator.TRUE_INT); - assertThat(b3Propagator.extract(carrier, getter)) + assertThat(getSpanContext(b3Propagator.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( SHORT_TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -153,7 +168,7 @@ public void extract_SampledContext_Bool_Short_TraceId() { carrier.put(B3Propagator.SPAN_ID_HEADER, SPAN_ID_BASE16); carrier.put(B3Propagator.SAMPLED_HEADER, "true"); - assertThat(b3Propagator.extract(carrier, getter)) + assertThat(getSpanContext(b3Propagator.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( SHORT_TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -166,7 +181,7 @@ public void extract_NotSampledContext_Short_TraceId() { carrier.put(B3Propagator.SPAN_ID_HEADER, SPAN_ID_BASE16); carrier.put(B3Propagator.SAMPLED_HEADER, B3Propagator.FALSE_INT); - assertThat(b3Propagator.extract(carrier, getter)) + assertThat(getSpanContext(b3Propagator.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( SHORT_TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_DEFAULT)); @@ -178,7 +193,7 @@ public void extract_InvalidTraceId() { invalidHeaders.put(B3Propagator.TRACE_ID_HEADER, "abcdefghijklmnopabcdefghijklmnop"); invalidHeaders.put(B3Propagator.SPAN_ID_HEADER, SPAN_ID_BASE16); invalidHeaders.put(B3Propagator.SAMPLED_HEADER, B3Propagator.TRUE_INT); - assertThat(b3Propagator.extract(invalidHeaders, getter)) + assertThat(getSpanContext(b3Propagator.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -188,7 +203,7 @@ public void extract_InvalidTraceId_Size() { invalidHeaders.put(B3Propagator.TRACE_ID_HEADER, TRACE_ID_BASE16 + "00"); invalidHeaders.put(B3Propagator.SPAN_ID_HEADER, SPAN_ID_BASE16); invalidHeaders.put(B3Propagator.SAMPLED_HEADER, B3Propagator.TRUE_INT); - assertThat(b3Propagator.extract(invalidHeaders, getter)) + assertThat(getSpanContext(b3Propagator.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -198,7 +213,7 @@ public void extract_InvalidSpanId() { invalidHeaders.put(B3Propagator.TRACE_ID_HEADER, TRACE_ID_BASE16); invalidHeaders.put(B3Propagator.SPAN_ID_HEADER, "abcdefghijklmnop"); invalidHeaders.put(B3Propagator.SAMPLED_HEADER, B3Propagator.TRUE_INT); - assertThat(b3Propagator.extract(invalidHeaders, getter)) + assertThat(getSpanContext(b3Propagator.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -208,7 +223,7 @@ public void extract_InvalidSpanId_Size() { invalidHeaders.put(B3Propagator.TRACE_ID_HEADER, TRACE_ID_BASE16); invalidHeaders.put(B3Propagator.SPAN_ID_HEADER, "abcdefghijklmnop" + "00"); invalidHeaders.put(B3Propagator.SAMPLED_HEADER, B3Propagator.TRUE_INT); - assertThat(b3Propagator.extract(invalidHeaders, getter)) + assertThat(getSpanContext(b3Propagator.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -216,7 +231,9 @@ public void extract_InvalidSpanId_Size() { public void inject_SampledContext_SingleHeader() { Map carrier = new LinkedHashMap<>(); b3PropagatorSingleHeader.inject( - SpanContext.create(TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT), + withSpanContext( + SpanContext.create(TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT), + Context.current()), carrier, setter); @@ -229,7 +246,9 @@ public void inject_SampledContext_SingleHeader() { public void inject_NotSampledContext_SingleHeader() { Map carrier = new LinkedHashMap<>(); b3PropagatorSingleHeader.inject( - SpanContext.create(TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_DEFAULT), + withSpanContext( + SpanContext.create(TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_DEFAULT), + Context.current()), carrier, setter); @@ -245,7 +264,7 @@ public void extract_SampledContext_Int_SingleHeader() { B3Propagator.COMBINED_HEADER, TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-" + B3Propagator.TRUE_INT); - assertThat(b3PropagatorSingleHeader.extract(carrier, getter)) + assertThat(getSpanContext(b3PropagatorSingleHeader.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -258,7 +277,7 @@ public void extract_SampledContext_DebugFlag_SingleHeader() { B3Propagator.COMBINED_HEADER, TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-" + B3Propagator.TRUE_INT + "-" + "0"); - assertThat(b3PropagatorSingleHeader.extract(carrier, getter)) + assertThat(getSpanContext(b3PropagatorSingleHeader.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -270,7 +289,7 @@ public void extract_SampledContext_Bool_SingleHeader() { carrier.put( B3Propagator.COMBINED_HEADER, TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-" + "true"); - assertThat(b3PropagatorSingleHeader.extract(carrier, getter)) + assertThat(getSpanContext(b3PropagatorSingleHeader.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -283,7 +302,7 @@ public void extract_SampledContext_Bool_DebugFlag_SingleHeader() { B3Propagator.COMBINED_HEADER, TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-" + "true" + "-" + "0"); - assertThat(b3PropagatorSingleHeader.extract(carrier, getter)) + assertThat(getSpanContext(b3PropagatorSingleHeader.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -296,7 +315,7 @@ public void extract_NotSampledContext_SingleHeader() { B3Propagator.COMBINED_HEADER, TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-" + B3Propagator.FALSE_INT); - assertThat(b3PropagatorSingleHeader.extract(carrier, getter)) + assertThat(getSpanContext(b3PropagatorSingleHeader.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_DEFAULT)); @@ -309,7 +328,7 @@ public void extract_SampledContext_Int_SingleHeader_Short_TraceId() { B3Propagator.COMBINED_HEADER, SHORT_TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-" + B3Propagator.TRUE_INT); - assertThat(b3PropagatorSingleHeader.extract(carrier, getter)) + assertThat(getSpanContext(b3PropagatorSingleHeader.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( SHORT_TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -322,7 +341,7 @@ public void extract_SampledContext_DebugFlag_SingleHeader_Short_TraceId() { B3Propagator.COMBINED_HEADER, SHORT_TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-" + B3Propagator.TRUE_INT + "-" + "0"); - assertThat(b3PropagatorSingleHeader.extract(carrier, getter)) + assertThat(getSpanContext(b3PropagatorSingleHeader.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( SHORT_TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -334,7 +353,7 @@ public void extract_SampledContext_Bool_SingleHeader_Short_TraceId() { carrier.put( B3Propagator.COMBINED_HEADER, SHORT_TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-" + "true"); - assertThat(b3PropagatorSingleHeader.extract(carrier, getter)) + assertThat(getSpanContext(b3PropagatorSingleHeader.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( SHORT_TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -347,7 +366,7 @@ public void extract_SampledContext_Bool_DebugFlag_SingleHeader_Short_TraceId() { B3Propagator.COMBINED_HEADER, SHORT_TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-" + "true" + "-" + "0"); - assertThat(b3PropagatorSingleHeader.extract(carrier, getter)) + assertThat(getSpanContext(b3PropagatorSingleHeader.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( SHORT_TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -360,7 +379,7 @@ public void extract_NotSampledContext_SingleHeader_Short_TraceId() { B3Propagator.COMBINED_HEADER, SHORT_TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-" + B3Propagator.FALSE_INT); - assertThat(b3PropagatorSingleHeader.extract(carrier, getter)) + assertThat(getSpanContext(b3PropagatorSingleHeader.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( SHORT_TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_DEFAULT)); @@ -371,7 +390,9 @@ public void extract_Null_SingleHeader() { Map invalidHeaders = new LinkedHashMap<>(); invalidHeaders.put(B3Propagator.COMBINED_HEADER, null); - assertThat(b3PropagatorSingleHeader.extract(invalidHeaders, getter)) + assertThat( + getSpanContext( + b3PropagatorSingleHeader.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -380,7 +401,9 @@ public void extract_Empty_SingleHeader() { Map invalidHeaders = new LinkedHashMap<>(); invalidHeaders.put(B3Propagator.COMBINED_HEADER, ""); - assertThat(b3PropagatorSingleHeader.extract(invalidHeaders, getter)) + assertThat( + getSpanContext( + b3PropagatorSingleHeader.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -391,7 +414,9 @@ public void extract_InvalidTraceId_SingleHeader() { B3Propagator.COMBINED_HEADER, "abcdefghijklmnopabcdefghijklmnop" + "-" + SPAN_ID_BASE16 + "-" + B3Propagator.TRUE_INT); - assertThat(b3PropagatorSingleHeader.extract(invalidHeaders, getter)) + assertThat( + getSpanContext( + b3PropagatorSingleHeader.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -407,7 +432,9 @@ public void extract_InvalidTraceId_Size_SingleHeader() { + "-" + B3Propagator.TRUE_INT); - assertThat(b3PropagatorSingleHeader.extract(invalidHeaders, getter)) + assertThat( + getSpanContext( + b3PropagatorSingleHeader.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -418,7 +445,9 @@ public void extract_InvalidSpanId_SingleHeader() { B3Propagator.COMBINED_HEADER, TRACE_ID_BASE16 + "-" + "abcdefghijklmnop" + "-" + B3Propagator.TRUE_INT); - assertThat(b3PropagatorSingleHeader.extract(invalidHeaders, getter)) + assertThat( + getSpanContext( + b3PropagatorSingleHeader.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -429,7 +458,7 @@ public void extract_InvalidSpanId_Size_SingleHeader() { B3Propagator.COMBINED_HEADER, TRACE_ID_BASE16 + "-" + "abcdefghijklmnop" + "00" + "-" + B3Propagator.TRUE_INT); - assertThat(b3Propagator.extract(invalidHeaders, getter)) + assertThat(getSpanContext(b3Propagator.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -438,7 +467,7 @@ public void extract_TooFewParts_SingleHeader() { Map invalidHeaders = new LinkedHashMap<>(); invalidHeaders.put(B3Propagator.COMBINED_HEADER, TRACE_ID_BASE16); - assertThat(b3Propagator.extract(invalidHeaders, getter)) + assertThat(getSpanContext(b3Propagator.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -449,7 +478,7 @@ public void extract_TooManyParts_SingleHeader() { B3Propagator.COMBINED_HEADER, TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-" + B3Propagator.TRUE_INT + "-extra"); - assertThat(b3Propagator.extract(invalidHeaders, getter)) + assertThat(getSpanContext(b3Propagator.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -470,6 +499,7 @@ public void headerNames() { @Test public void extract_emptyCarrier() { Map emptyHeaders = new HashMap<>(); - assertThat(b3Propagator.extract(emptyHeaders, getter)).isEqualTo(SpanContext.getInvalid()); + assertThat(getSpanContext(b3Propagator.extract(Context.current(), emptyHeaders, getter))) + .isEqualTo(SpanContext.getInvalid()); } } diff --git a/api/src/test/java/io/opentelemetry/trace/propagation/HttpTraceContextTest.java b/api/src/test/java/io/opentelemetry/trace/propagation/HttpTraceContextTest.java index cf5bd9abd39..40f507abee2 100644 --- a/api/src/test/java/io/opentelemetry/trace/propagation/HttpTraceContextTest.java +++ b/api/src/test/java/io/opentelemetry/trace/propagation/HttpTraceContextTest.java @@ -20,13 +20,16 @@ import static io.opentelemetry.trace.propagation.HttpTraceContext.TRACE_PARENT; import static io.opentelemetry.trace.propagation.HttpTraceContext.TRACE_STATE; +import io.grpc.Context; import io.opentelemetry.context.propagation.HttpTextFormat.Getter; import io.opentelemetry.context.propagation.HttpTextFormat.Setter; +import io.opentelemetry.trace.DefaultSpan; import io.opentelemetry.trace.SpanContext; import io.opentelemetry.trace.SpanId; import io.opentelemetry.trace.TraceFlags; import io.opentelemetry.trace.TraceId; import io.opentelemetry.trace.TraceState; +import io.opentelemetry.trace.TracingContextUtils; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -77,33 +80,51 @@ public String get(Map carrier, String key) { private final HttpTraceContext httpTraceContext = new HttpTraceContext(); @Rule public ExpectedException thrown = ExpectedException.none(); + private static SpanContext getSpanContext(Context context) { + return TracingContextUtils.getSpan(context).getContext(); + } + + private static Context withSpanContext(SpanContext spanContext, Context context) { + return TracingContextUtils.withSpan(DefaultSpan.create(spanContext), context); + } + + @Test + public void inject_Nothing() { + Map carrier = new LinkedHashMap(); + httpTraceContext.inject(Context.current(), carrier, setter); + assertThat(carrier).hasSize(0); + } + @Test public void inject_SampledContext() { Map carrier = new LinkedHashMap<>(); - httpTraceContext.inject( - SpanContext.create(TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT), - carrier, - setter); + Context context = + withSpanContext( + SpanContext.create(TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT), + Context.current()); + httpTraceContext.inject(context, carrier, setter); assertThat(carrier).containsExactly(TRACE_PARENT, TRACEPARENT_HEADER_SAMPLED); } @Test public void inject_NotSampledContext() { Map carrier = new LinkedHashMap<>(); - httpTraceContext.inject( - SpanContext.create(TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_DEFAULT), - carrier, - setter); + Context context = + withSpanContext( + SpanContext.create(TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_DEFAULT), + Context.current()); + httpTraceContext.inject(context, carrier, setter); assertThat(carrier).containsExactly(TRACE_PARENT, TRACEPARENT_HEADER_NOT_SAMPLED); } @Test public void inject_SampledContext_WithTraceState() { Map carrier = new LinkedHashMap<>(); - httpTraceContext.inject( - SpanContext.create(TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_NOT_DEFAULT), - carrier, - setter); + Context context = + withSpanContext( + SpanContext.create(TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_NOT_DEFAULT), + Context.current()); + httpTraceContext.inject(context, carrier, setter); assertThat(carrier) .containsExactly( TRACE_PARENT, TRACEPARENT_HEADER_SAMPLED, TRACE_STATE, TRACESTATE_NOT_DEFAULT_ENCODING); @@ -112,10 +133,11 @@ public void inject_SampledContext_WithTraceState() { @Test public void inject_NotSampledContext_WithTraceState() { Map carrier = new LinkedHashMap<>(); - httpTraceContext.inject( - SpanContext.create(TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_NOT_DEFAULT), - carrier, - setter); + Context context = + withSpanContext( + SpanContext.create(TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_NOT_DEFAULT), + Context.current()); + httpTraceContext.inject(context, carrier, setter); assertThat(carrier) .containsExactly( TRACE_PARENT, @@ -128,7 +150,7 @@ public void inject_NotSampledContext_WithTraceState() { public void extract_SampledContext() { Map carrier = new LinkedHashMap<>(); carrier.put(TRACE_PARENT, TRACEPARENT_HEADER_SAMPLED); - assertThat(httpTraceContext.extract(carrier, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -138,7 +160,7 @@ public void extract_SampledContext() { public void extract_NotSampledContext() { Map carrier = new LinkedHashMap<>(); carrier.put(TRACE_PARENT, TRACEPARENT_HEADER_NOT_SAMPLED); - assertThat(httpTraceContext.extract(carrier, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_DEFAULT)); @@ -149,7 +171,7 @@ public void extract_SampledContext_WithTraceState() { Map carrier = new LinkedHashMap<>(); carrier.put(TRACE_PARENT, TRACEPARENT_HEADER_SAMPLED); carrier.put(TRACE_STATE, TRACESTATE_NOT_DEFAULT_ENCODING); - assertThat(httpTraceContext.extract(carrier, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_NOT_DEFAULT)); @@ -160,7 +182,7 @@ public void extract_NotSampledContext_WithTraceState() { Map carrier = new LinkedHashMap<>(); carrier.put(TRACE_PARENT, TRACEPARENT_HEADER_NOT_SAMPLED); carrier.put(TRACE_STATE, TRACESTATE_NOT_DEFAULT_ENCODING); - assertThat(httpTraceContext.extract(carrier, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_NOT_DEFAULT)); @@ -170,7 +192,7 @@ public void extract_NotSampledContext_WithTraceState() { public void extract_NotSampledContext_NextVersion() { Map carrier = new LinkedHashMap<>(); carrier.put(TRACE_PARENT, "01-" + TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-00-02"); - assertThat(httpTraceContext.extract(carrier, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_DEFAULT)); @@ -181,7 +203,7 @@ public void extract_NotSampledContext_EmptyTraceState() { Map carrier = new LinkedHashMap<>(); carrier.put(TRACE_PARENT, TRACEPARENT_HEADER_NOT_SAMPLED); carrier.put(TRACE_STATE, ""); - assertThat(httpTraceContext.extract(carrier, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_DEFAULT)); @@ -192,7 +214,7 @@ public void extract_NotSampledContext_TraceStateWithSpaces() { Map carrier = new LinkedHashMap<>(); carrier.put(TRACE_PARENT, TRACEPARENT_HEADER_NOT_SAMPLED); carrier.put(TRACE_STATE, TRACESTATE_NOT_DEFAULT_ENCODING_WITH_SPACES); - assertThat(httpTraceContext.extract(carrier, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), carrier, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TRACE_STATE_NOT_DEFAULT)); @@ -203,7 +225,7 @@ public void extract_InvalidTraceId() { Map invalidHeaders = new LinkedHashMap<>(); invalidHeaders.put( TRACE_PARENT, "00-" + "abcdefghijklmnopabcdefghijklmnop" + "-" + SPAN_ID_BASE16 + "-01"); - assertThat(httpTraceContext.extract(invalidHeaders, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -211,15 +233,15 @@ public void extract_InvalidTraceId() { public void extract_InvalidTraceId_Size() { Map invalidHeaders = new LinkedHashMap<>(); invalidHeaders.put(TRACE_PARENT, "00-" + TRACE_ID_BASE16 + "00-" + SPAN_ID_BASE16 + "-01"); - assertThat(httpTraceContext.extract(invalidHeaders, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @Test public void extract_InvalidSpanId() { - Map invalidHeaders = new HashMap<>(); + Map invalidHeaders = new HashMap(); invalidHeaders.put(TRACE_PARENT, "00-" + TRACE_ID_BASE16 + "-" + "abcdefghijklmnop" + "-01"); - assertThat(httpTraceContext.extract(invalidHeaders, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -227,7 +249,7 @@ public void extract_InvalidSpanId() { public void extract_InvalidSpanId_Size() { Map invalidHeaders = new HashMap<>(); invalidHeaders.put(TRACE_PARENT, "00-" + TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "00-01"); - assertThat(httpTraceContext.extract(invalidHeaders, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -235,7 +257,7 @@ public void extract_InvalidSpanId_Size() { public void extract_InvalidTraceFlags() { Map invalidHeaders = new HashMap<>(); invalidHeaders.put(TRACE_PARENT, "00-" + TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-gh"); - assertThat(httpTraceContext.extract(invalidHeaders, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @@ -243,38 +265,38 @@ public void extract_InvalidTraceFlags() { public void extract_InvalidTraceFlags_Size() { Map invalidHeaders = new HashMap<>(); invalidHeaders.put(TRACE_PARENT, "00-" + TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-0100"); - assertThat(httpTraceContext.extract(invalidHeaders, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), invalidHeaders, getter))) .isSameInstanceAs(SpanContext.getInvalid()); } @Test - public void extract_InvalidTraceState_EntriesDelimiter() { + public void extract_InvalidTracestate_EntriesDelimiter() { Map invalidHeaders = new HashMap<>(); invalidHeaders.put(TRACE_PARENT, "00-" + TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-01"); invalidHeaders.put(TRACE_STATE, "foo=bar;test=test"); - assertThat(httpTraceContext.extract(invalidHeaders, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), invalidHeaders, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); } @Test - public void extract_InvalidTraceState_KeyValueDelimiter() { + public void extract_InvalidTracestate_KeyValueDelimiter() { Map invalidHeaders = new HashMap<>(); invalidHeaders.put(TRACE_PARENT, "00-" + TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-01"); invalidHeaders.put(TRACE_STATE, "foo=bar,test-test"); - assertThat(httpTraceContext.extract(invalidHeaders, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), invalidHeaders, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); } @Test - public void extract_InvalidTraceState_OneString() { + public void extract_InvalidTracestate_OneString() { Map invalidHeaders = new HashMap<>(); invalidHeaders.put(TRACE_PARENT, "00-" + TRACE_ID_BASE16 + "-" + SPAN_ID_BASE16 + "-01"); invalidHeaders.put(TRACE_STATE, "test-test"); - assertThat(httpTraceContext.extract(invalidHeaders, getter)) + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), invalidHeaders, getter))) .isEqualTo( SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, SAMPLED_TRACE_OPTIONS, TRACE_STATE_DEFAULT)); @@ -294,6 +316,7 @@ public void headerNames() { @Test public void extract_emptyCarrier() { Map emptyHeaders = new HashMap<>(); - assertThat(httpTraceContext.extract(emptyHeaders, getter)).isEqualTo(SpanContext.getInvalid()); + assertThat(getSpanContext(httpTraceContext.extract(Context.current(), emptyHeaders, getter))) + .isSameInstanceAs(SpanContext.getInvalid()); } } diff --git a/context_prop/src/main/java/io/opentelemetry/context/propagation/ContextPropagators.java b/context_prop/src/main/java/io/opentelemetry/context/propagation/ContextPropagators.java new file mode 100644 index 00000000000..823909985b0 --- /dev/null +++ b/context_prop/src/main/java/io/opentelemetry/context/propagation/ContextPropagators.java @@ -0,0 +1,94 @@ +/* + * Copyright 2019, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opentelemetry.context.propagation; + +import javax.annotation.concurrent.ThreadSafe; + +/** + * A container of the registered propagators for every supported format. + * + *

This container can be used to access a single, composite propagator for each supported format, + * which will be responsible for injecting and extracting data for each registered concern (traces, + * correlations, etc). Propagation will happen through {@code io.grpc.Context}, from which values + * will be read upon injection, and which will store values from the extraction step. The resulting + * {@code Context} can then be used implicitly or explicitly by the OpenTelemetry API. + * + *

Example of usage on the client: + * + *

{@code
+ * private static final Tracer tracer = OpenTelemetry.getTracer();
+ * void onSendRequest() {
+ *   try (Scope scope = tracer.withSpan(span)) {
+ *     ContextPropagators propagators = OpenTelemetry.getPropagators();
+ *     HttpTextFormat textFormat = propagators.getHttpTextFormat();
+ *
+ *     // Inject the span's SpanContext and other available concerns (such as correlations)
+ *     // contained in the specified Context.
+ *     Map map = new HashMap<>();
+ *     httpTextFormat.inject(Context.current(), map, new Setter() {
+ *       public void put(Map map, String key, String value) {
+ *         map.put(key, value);
+ *       }
+ *     });
+ *     // Send the request including the text map and wait for the response.
+ *   }
+ * }
+ * }
+ * + *

Example of usage in the server: + * + *

{@code
+ * private static final Tracer tracer = OpenTelemetry.getTracer();
+ * void onRequestReceived() {
+ *   ContextPropagators propagators = OpenTelemetry.getPropagators();
+ *   HttpTextFormat textFormat = propagators.getHttpTextFormat();
+ *
+ *   // Extract and store the propagated span's SpanContext and other available concerns
+ *   // in the specified Context.
+ *   Context context = textFormat.extract(Context.current(), request, new Getter() {
+ *     public String get(Object request, String key) {
+ *       // Return the value associated to the key, if available.
+ *     }
+ *   });
+ *   Span span = tracer.spanBuilder("MyRequest")
+ *       .setParent(context)
+ *       .setSpanKind(Span.Kind.SERVER).startSpan();
+ *   try (Scope ss = tracer.withSpan(span)) {
+ *     // Handle request and send response back.
+ *   } finally {
+ *     span.end();
+ *   }
+ * }
+ * }
+ * + * @since 0.3.0 + */ +@ThreadSafe +public interface ContextPropagators { + + /** + * Returns a {@link HttpTextFormat} propagator. + * + *

The returned value will be a composite instance containing all the registered {@link + * HttpTextFormat} propagators. If none is registered, the returned value will be a no-op + * instance. + * + * @return the {@link HttpTextFormat} propagator to inject and extract data. + * @since 0.3.0 + */ + HttpTextFormat getHttpTextFormat(); +} diff --git a/context_prop/src/main/java/io/opentelemetry/context/propagation/DefaultContextPropagators.java b/context_prop/src/main/java/io/opentelemetry/context/propagation/DefaultContextPropagators.java new file mode 100644 index 00000000000..b09751e77e7 --- /dev/null +++ b/context_prop/src/main/java/io/opentelemetry/context/propagation/DefaultContextPropagators.java @@ -0,0 +1,166 @@ +/* + * Copyright 2019, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opentelemetry.context.propagation; + +import io.grpc.Context; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * {@code DefaultContextPropagators} is the default, built-in implementation of {@link + * ContextPropagators}. + * + *

All the registered propagators are stored internally as a simple list, and are invoked + * synchronically upon injection and extraction. + * + * @since 0.3.0 + */ +public final class DefaultContextPropagators implements ContextPropagators { + private final HttpTextFormat textFormat; + + @Override + public HttpTextFormat getHttpTextFormat() { + return textFormat; + } + + /** + * Returns a {@link DefaultContextPropagators.Builder} to create a new {@link ContextPropagators} + * object. + * + * @return a {@link DefaultContextPropagators.Builder}. + * @since 0.3.0 + */ + public static Builder builder() { + return new Builder(); + } + + private DefaultContextPropagators(HttpTextFormat textFormat) { + this.textFormat = textFormat; + } + + /** + * {@link Builder} is used to construct a new {@code ContextPropagators} object with the specified + * propagators. + * + *

This is a example of a {@code ContextPropagators} object being created: + * + *

{@code
+   * ContextPropagators propagators = DefaultContextPropagators.builder()
+   *     .addHttpTextFormat(new HttpTraceContext())
+   *     .addHttpTextFormat(new HttpCorrelationContext())
+   *     .addHttpTextFormat(new MyCustomContextPropagator())
+   *     .build();
+   * }
+ * + * @since 0.3.0 + */ + public static final class Builder { + List textPropagators = new ArrayList<>(); + + /** + * Adds a {@link HttpTextFormat} propagator. + * + *

One propagator per concern (traces, correlations, etc) should be added if this format is + * supported. + * + * @param textFormat the propagator to be added. + * @return this. + * @throws NullPointerException if {@code textFormat} is {@code null}. + * @since 0.3.0 + */ + public Builder addHttpTextFormat(HttpTextFormat textFormat) { + if (textFormat == null) { + throw new NullPointerException("textFormat"); + } + + textPropagators.add(textFormat); + return this; + } + + /** + * Builds a new {@code ContextPropagators} with the specified propagators. + * + * @return the newly created {@code ContextPropagators} instance. + * @since 0.3.0 + */ + public ContextPropagators build() { + if (textPropagators.isEmpty()) { + return new DefaultContextPropagators(NoopHttpTextFormat.INSTANCE); + } + + return new DefaultContextPropagators(new MultiHttpTextFormat(textPropagators)); + } + } + + private static final class MultiHttpTextFormat implements HttpTextFormat { + private final HttpTextFormat[] textPropagators; + private final List allFields; + + private MultiHttpTextFormat(List textPropagators) { + this.textPropagators = new HttpTextFormat[textPropagators.size()]; + textPropagators.toArray(this.textPropagators); + this.allFields = getAllFields(this.textPropagators); + } + + @Override + public List fields() { + return allFields; + } + + private static List getAllFields(HttpTextFormat[] textPropagators) { + List fields = new ArrayList<>(); + for (int i = 0; i < textPropagators.length; i++) { + fields.addAll(textPropagators[i].fields()); + } + + return fields; + } + + @Override + public void inject(Context context, C carrier, Setter setter) { + for (int i = 0; i < textPropagators.length; i++) { + textPropagators[i].inject(context, carrier, setter); + } + } + + @Override + public Context extract(Context context, C carrier, Getter getter) { + for (int i = 0; i < textPropagators.length; i++) { + context = textPropagators[i].extract(context, carrier, getter); + } + return context; + } + } + + private static final class NoopHttpTextFormat implements HttpTextFormat { + private static final NoopHttpTextFormat INSTANCE = new NoopHttpTextFormat(); + + @Override + public List fields() { + return Collections.emptyList(); + } + + @Override + public void inject(Context context, C carrier, Setter setter) {} + + @Override + public Context extract(Context context, C carrier, Getter getter) { + return context; + } + } +} diff --git a/context_prop/src/main/java/io/opentelemetry/context/propagation/HttpTextFormat.java b/context_prop/src/main/java/io/opentelemetry/context/propagation/HttpTextFormat.java index 26f3ece22cd..b8bb14f0144 100644 --- a/context_prop/src/main/java/io/opentelemetry/context/propagation/HttpTextFormat.java +++ b/context_prop/src/main/java/io/opentelemetry/context/propagation/HttpTextFormat.java @@ -16,6 +16,7 @@ package io.opentelemetry.context.propagation; +import io.grpc.Context; import java.util.List; import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; @@ -29,13 +30,31 @@ * usually an http request. Propagation is usually implemented via library- specific request * interceptors, where the client-side injects values and the server-side extracts them. * + *

Specific concern values (traces, correlations, etc) will be read from the specified {@code + * Context}, and resulting values will be stored in a new {@code Context} upon extraction. It is + * recommended to use a single {@code Context.Key} to store the entire concern data: + * + *

{@code
+ * public static final Context.Key CONCERN_KEY = Context.key("my-concern-key");
+ * public MyConcernPropagator implements HttpTextFormat {
+ *   public  void inject(Context context, C carrier, Setter setter) {
+ *     Object concern = CONCERN_KEY.get(context);
+ *     // Use concern in the specified context to propagate data.
+ *   }
+ *   public  Context extract(Context context, C carrier, Getter setter) {
+ *     // Use setter to get the data from the carrier.
+ *     return context.withValue(CONCERN_KEY, concern);
+ *   }
+ * }
+ * }
+ * * @since 0.1.0 */ @ThreadSafe -public interface HttpTextFormat { +public interface HttpTextFormat { /** * The propagation fields defined. If your carrier is reused, you should delete the fields here - * before calling {@link #inject(Object, Object, Setter)} )}. + * before calling {@link #inject(Context, Object, Setter)} )}. * *

For example, if the carrier is a single-use or immutable request object, you don't need to * clear fields as they couldn't have been set before. If it is a mutable, retryable object, @@ -52,13 +71,13 @@ public interface HttpTextFormat { /** * Injects the value downstream. For example, as http headers. * - * @param value the value to be injected. + * @param context the {@code Context} containing the value to be injected. * @param carrier holds propagation fields. For example, an outgoing message or http request. * @param setter invoked for each propagation key to add or remove. * @param carrier of propagation fields, such as an http request * @since 0.1.0 */ - void inject(V value, C carrier, Setter setter); + void inject(Context context, C carrier, Setter setter); /** * Class that allows a {@code HttpTextFormat} to set propagated fields into a carrier. @@ -88,18 +107,18 @@ interface Setter { /** * Extracts the value from upstream. For example, as http headers. * - *

If the value could not be parsed, the underlying implementation will decide to return an - * object representing either an empty value, an invalid value, or a valid value. Implementation - * must not return {@code null}. + *

If the value could not be parsed, the underlying implementation will decide to set an object + * representing either an empty value, an invalid value, or a valid value. Implementation must not + * set {@code null}. * + * @param context the {@code Context} used to store the extracted value. * @param carrier holds propagation fields. For example, an outgoing message or http request. * @param getter invoked for each propagation key to get. * @param carrier of propagation fields, such as an http request. - * @return the extracted value or an invalid span context if getter returned {@code null}, never - * {@code null}. + * @return the {@code Context} containing the extracted value. * @since 0.1.0 */ - V extract(C carrier, Getter getter); + Context extract(Context context, C carrier, Getter getter); /** * Interface that allows a {@code HttpTextFormat} to read propagated fields from a carrier. diff --git a/context_prop/src/test/java/io/opentelemetry/context/propagation/DefaultPropagatorsTest.java b/context_prop/src/test/java/io/opentelemetry/context/propagation/DefaultPropagatorsTest.java new file mode 100644 index 00000000000..08d419c7e22 --- /dev/null +++ b/context_prop/src/test/java/io/opentelemetry/context/propagation/DefaultPropagatorsTest.java @@ -0,0 +1,162 @@ +/* + * Copyright 2019, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opentelemetry.context.propagation; + +import static com.google.common.truth.Truth.assertThat; + +import io.grpc.Context; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link DefaultContextPropagators}. */ +@RunWith(JUnit4.class) +public class DefaultPropagatorsTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void addHttpTextFormatNull() { + thrown.expect(NullPointerException.class); + DefaultContextPropagators.builder().addHttpTextFormat(null); + } + + @Test + public void testInject() { + CustomHttpTextFormat propagator1 = new CustomHttpTextFormat("prop1"); + CustomHttpTextFormat propagator2 = new CustomHttpTextFormat("prop2"); + ContextPropagators propagators = + DefaultContextPropagators.builder() + .addHttpTextFormat(propagator1) + .addHttpTextFormat(propagator2) + .build(); + + Context context = Context.current(); + context = context.withValue(propagator1.getKey(), "value1"); + context = context.withValue(propagator2.getKey(), "value2"); + + Map map = new HashMap<>(); + propagators.getHttpTextFormat().inject(context, map, MapSetter.INSTANCE); + assertThat(map.get(propagator1.getKeyName())).isEqualTo("value1"); + assertThat(map.get(propagator2.getKeyName())).isEqualTo("value2"); + } + + @Test + public void testExtract() { + CustomHttpTextFormat propagator1 = new CustomHttpTextFormat("prop1"); + CustomHttpTextFormat propagator2 = new CustomHttpTextFormat("prop2"); + CustomHttpTextFormat propagator3 = new CustomHttpTextFormat("prop3"); + ContextPropagators propagators = + DefaultContextPropagators.builder() + .addHttpTextFormat(propagator1) + .addHttpTextFormat(propagator2) + .build(); + + // Put values for propagators 1 and 2 only. + Map map = new HashMap<>(); + map.put(propagator1.getKeyName(), "value1"); + map.put(propagator2.getKeyName(), "value2"); + + Context context = + propagators.getHttpTextFormat().extract(Context.current(), map, MapGetter.INSTANCE); + assertThat(propagator1.getKey().get(context)).isEqualTo("value1"); + assertThat(propagator2.getKey().get(context)).isEqualTo("value2"); + assertThat(propagator3.getKey().get(context)).isNull(); // Handle missing value. + } + + @Test + public void noopPropagator() { + ContextPropagators propagators = DefaultContextPropagators.builder().build(); + + Context context = Context.current(); + Map map = new HashMap<>(); + propagators.getHttpTextFormat().inject(context, map, MapSetter.INSTANCE); + assertThat(map).isEmpty(); + + assertThat(propagators.getHttpTextFormat().extract(context, map, MapGetter.INSTANCE)) + .isSameInstanceAs(context); + } + + class CustomHttpTextFormat implements HttpTextFormat { + private final String name; + private final Context.Key key; + + public CustomHttpTextFormat(String name) { + this.name = name; + this.key = Context.key(name); + } + + public Context.Key getKey() { + return key; + } + + public String getKeyName() { + return name; + } + + @Override + public List fields() { + return Collections.singletonList(name); + } + + @Override + public void inject(Context context, C carrier, Setter setter) { + Object payload = key.get(context); + if (payload != null) { + setter.set(carrier, name, payload.toString()); + } + } + + @Override + public Context extract(Context context, C carrier, Getter getter) { + String payload = getter.get(carrier, name); + if (payload != null) { + context = context.withValue(key, payload); + } + + return context; + } + } + + private static final class MapSetter implements HttpTextFormat.Setter> { + private static final MapSetter INSTANCE = new MapSetter(); + + @Override + public void set(Map map, String key, String value) { + map.put(key, value); + } + + private MapSetter() {} + } + + private static final class MapGetter implements HttpTextFormat.Getter> { + private static final MapGetter INSTANCE = new MapGetter(); + + @Override + public String get(Map map, String key) { + return map.get(key); + } + + private MapGetter() {} + } +} diff --git a/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/BaseShimObject.java b/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/BaseShimObject.java index 1e31c8dabf5..53f9389197f 100644 --- a/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/BaseShimObject.java +++ b/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/BaseShimObject.java @@ -16,6 +16,7 @@ package io.opentelemetry.opentracingshim; +import io.opentelemetry.context.propagation.ContextPropagators; import io.opentelemetry.correlationcontext.CorrelationContextManager; import io.opentelemetry.trace.Tracer; @@ -41,4 +42,8 @@ CorrelationContextManager contextManager() { SpanContextShimTable spanContextTable() { return telemetryInfo.spanContextTable(); } + + ContextPropagators propagators() { + return telemetryInfo.propagators(); + } } diff --git a/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java b/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java index 2852cc58030..fdd1c3ad62c 100644 --- a/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java +++ b/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java @@ -16,7 +16,11 @@ package io.opentelemetry.opentracingshim; +import io.grpc.Context; import io.opentelemetry.context.propagation.HttpTextFormat; +import io.opentelemetry.correlationcontext.CorrelationsContextUtils; +import io.opentelemetry.trace.DefaultSpan; +import io.opentelemetry.trace.TracingContextUtils; import io.opentracing.propagation.TextMapExtract; import io.opentracing.propagation.TextMapInject; import java.util.HashMap; @@ -29,12 +33,14 @@ final class Propagation extends BaseShimObject { } public void injectTextFormat(SpanContextShim contextShim, TextMapInject carrier) { - tracer() - .getHttpTextFormat() - .inject(contextShim.getSpanContext(), carrier, TextMapSetter.INSTANCE); - contextManager() - .getHttpTextFormat() - .inject(contextShim.getCorrelationContext(), carrier, TextMapSetter.INSTANCE); + Context context = + TracingContextUtils.withSpan( + DefaultSpan.create(contextShim.getSpanContext()), Context.current()); + context = + CorrelationsContextUtils.withCorrelationContext( + contextShim.getCorrelationContext(), context); + + propagators().getHttpTextFormat().inject(context, carrier, TextMapSetter.INSTANCE); } @Nullable @@ -44,14 +50,18 @@ public SpanContextShim extractTextFormat(TextMapExtract carrier) { carrierMap.put(entry.getKey(), entry.getValue()); } - io.opentelemetry.trace.SpanContext context = - tracer().getHttpTextFormat().extract(carrierMap, TextMapGetter.INSTANCE); - io.opentelemetry.correlationcontext.CorrelationContext distContext = - contextManager().getHttpTextFormat().extract(carrierMap, TextMapGetter.INSTANCE); - if (!context.isValid()) { + Context context = + propagators() + .getHttpTextFormat() + .extract(Context.current(), carrierMap, TextMapGetter.INSTANCE); + + io.opentelemetry.trace.Span span = TracingContextUtils.getSpan(context); + if (!span.getContext().isValid()) { return null; } - return new SpanContextShim(telemetryInfo, context, distContext); + + return new SpanContextShim( + telemetryInfo, span.getContext(), CorrelationsContextUtils.getCorrelationContext(context)); } static final class TextMapSetter implements HttpTextFormat.Setter { diff --git a/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/TelemetryInfo.java b/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/TelemetryInfo.java index e0add125825..1af59880015 100644 --- a/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/TelemetryInfo.java +++ b/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/TelemetryInfo.java @@ -16,6 +16,7 @@ package io.opentelemetry.opentracingshim; +import io.opentelemetry.context.propagation.ContextPropagators; import io.opentelemetry.correlationcontext.CorrelationContext; import io.opentelemetry.correlationcontext.CorrelationContextManager; import io.opentelemetry.trace.Tracer; @@ -28,11 +29,14 @@ final class TelemetryInfo { private final Tracer tracer; private final CorrelationContextManager contextManager; private final CorrelationContext emptyCorrelationContext; + private final ContextPropagators propagators; private final SpanContextShimTable spanContextTable; - TelemetryInfo(Tracer tracer, CorrelationContextManager contextManager) { + TelemetryInfo( + Tracer tracer, CorrelationContextManager contextManager, ContextPropagators propagators) { this.tracer = tracer; this.contextManager = contextManager; + this.propagators = propagators; this.emptyCorrelationContext = contextManager.contextBuilder().build(); this.spanContextTable = new SpanContextShimTable(); } @@ -52,4 +56,8 @@ SpanContextShimTable spanContextTable() { CorrelationContext emptyCorrelationContext() { return emptyCorrelationContext; } + + ContextPropagators propagators() { + return propagators; + } } diff --git a/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/TraceShim.java b/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/TraceShim.java index 545c93d5464..36cb67ecc67 100644 --- a/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/TraceShim.java +++ b/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/TraceShim.java @@ -36,7 +36,8 @@ public static io.opentracing.Tracer createTracerShim() { return new TracerShim( new TelemetryInfo( getTracer(OpenTelemetry.getTracerProvider()), - OpenTelemetry.getCorrelationContextManager())); + OpenTelemetry.getCorrelationContextManager(), + OpenTelemetry.getPropagators())); } /** @@ -53,7 +54,8 @@ public static io.opentracing.Tracer createTracerShim( return new TracerShim( new TelemetryInfo( getTracer(Utils.checkNotNull(tracerProvider, "tracerProvider")), - Utils.checkNotNull(contextManager, "contextManager"))); + Utils.checkNotNull(contextManager, "contextManager"), + OpenTelemetry.getPropagators())); } private static Tracer getTracer(TracerProvider tracerProvider) { diff --git a/opentracing_shim/src/test/java/io/opentelemetry/opentracingshim/SpanBuilderShimTest.java b/opentracing_shim/src/test/java/io/opentelemetry/opentracingshim/SpanBuilderShimTest.java index da17624a366..46dbe1fb88d 100644 --- a/opentracing_shim/src/test/java/io/opentelemetry/opentracingshim/SpanBuilderShimTest.java +++ b/opentracing_shim/src/test/java/io/opentelemetry/opentracingshim/SpanBuilderShimTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import io.opentelemetry.OpenTelemetry; import io.opentelemetry.sdk.correlationcontext.CorrelationContextManagerSdk; import io.opentelemetry.sdk.trace.TracerSdkProvider; import io.opentelemetry.trace.Tracer; @@ -29,7 +30,7 @@ public class SpanBuilderShimTest { private final TracerSdkProvider tracerSdkFactory = TracerSdkProvider.builder().build(); private final Tracer tracer = tracerSdkFactory.get("SpanShimTest"); private final TelemetryInfo telemetryInfo = - new TelemetryInfo(tracer, new CorrelationContextManagerSdk()); + new TelemetryInfo(tracer, new CorrelationContextManagerSdk(), OpenTelemetry.getPropagators()); private static final String SPAN_NAME = "Span"; diff --git a/opentracing_shim/src/test/java/io/opentelemetry/opentracingshim/SpanShimTest.java b/opentracing_shim/src/test/java/io/opentelemetry/opentracingshim/SpanShimTest.java index 401295ee61b..7eef430695d 100644 --- a/opentracing_shim/src/test/java/io/opentelemetry/opentracingshim/SpanShimTest.java +++ b/opentracing_shim/src/test/java/io/opentelemetry/opentracingshim/SpanShimTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import io.opentelemetry.OpenTelemetry; import io.opentelemetry.sdk.correlationcontext.CorrelationContextManagerSdk; import io.opentelemetry.sdk.trace.TracerSdkProvider; import io.opentelemetry.trace.Tracer; @@ -35,7 +36,7 @@ public class SpanShimTest { private final TracerSdkProvider tracerSdkFactory = TracerSdkProvider.builder().build(); private final Tracer tracer = tracerSdkFactory.get("SpanShimTest"); private final TelemetryInfo telemetryInfo = - new TelemetryInfo(tracer, new CorrelationContextManagerSdk()); + new TelemetryInfo(tracer, new CorrelationContextManagerSdk(), OpenTelemetry.getPropagators()); private io.opentelemetry.trace.Span span; private static final String SPAN_NAME = "Span"; diff --git a/opentracing_shim/src/test/java/io/opentelemetry/opentracingshim/TracerShimTest.java b/opentracing_shim/src/test/java/io/opentelemetry/opentracingshim/TracerShimTest.java index fe3f319c86f..3ded967b92f 100644 --- a/opentracing_shim/src/test/java/io/opentelemetry/opentracingshim/TracerShimTest.java +++ b/opentracing_shim/src/test/java/io/opentelemetry/opentracingshim/TracerShimTest.java @@ -43,7 +43,8 @@ public void setUp() { new TracerShim( new TelemetryInfo( OpenTelemetry.getTracerProvider().get("opentracingshim"), - OpenTelemetry.getCorrelationContextManager())); + OpenTelemetry.getCorrelationContextManager(), + OpenTelemetry.getPropagators())); } @Test diff --git a/sdk/src/main/java/io/opentelemetry/sdk/correlationcontext/CorrelationContextManagerSdk.java b/sdk/src/main/java/io/opentelemetry/sdk/correlationcontext/CorrelationContextManagerSdk.java index 5c61403da37..1e009d0a658 100644 --- a/sdk/src/main/java/io/opentelemetry/sdk/correlationcontext/CorrelationContextManagerSdk.java +++ b/sdk/src/main/java/io/opentelemetry/sdk/correlationcontext/CorrelationContextManagerSdk.java @@ -17,11 +17,9 @@ package io.opentelemetry.sdk.correlationcontext; import io.opentelemetry.context.Scope; -import io.opentelemetry.context.propagation.HttpTextFormat; import io.opentelemetry.correlationcontext.CorrelationContext; import io.opentelemetry.correlationcontext.CorrelationContextManager; import io.opentelemetry.correlationcontext.CorrelationsContextUtils; -import io.opentelemetry.correlationcontext.DefaultCorrelationContextManager; /** * {@link CorrelationContextManagerSdk} is SDK implementation of {@link CorrelationContextManager}. @@ -42,10 +40,4 @@ public CorrelationContext.Builder contextBuilder() { public Scope withContext(CorrelationContext distContext) { return CorrelationsContextUtils.currentContextWith(distContext); } - - @Override - public HttpTextFormat getHttpTextFormat() { - // TODO: Implement this. - return DefaultCorrelationContextManager.getInstance().getHttpTextFormat(); - } } diff --git a/sdk/src/main/java/io/opentelemetry/sdk/trace/SpanBuilderSdk.java b/sdk/src/main/java/io/opentelemetry/sdk/trace/SpanBuilderSdk.java index 345cb3b7e50..cf3d9fef1b4 100644 --- a/sdk/src/main/java/io/opentelemetry/sdk/trace/SpanBuilderSdk.java +++ b/sdk/src/main/java/io/opentelemetry/sdk/trace/SpanBuilderSdk.java @@ -16,6 +16,7 @@ package io.opentelemetry.sdk.trace; +import io.grpc.Context; import io.opentelemetry.common.AttributeValue; import io.opentelemetry.internal.Utils; import io.opentelemetry.sdk.common.Clock; @@ -62,7 +63,7 @@ final class SpanBuilderSdk implements Span.Builder { private final AttributesWithCapacity attributes; private List links; private int totalNumberOfLinksAdded = 0; - private ParentType parentType = ParentType.CURRENT_SPAN; + private ParentType parentType = ParentType.CURRENT_CONTEXT; private long startEpochNanos = 0; SpanBuilderSdk( @@ -260,12 +261,11 @@ private static Clock getClock(Span parent, Clock clock) { @Nullable private static SpanContext parent( ParentType parentType, Span explicitParent, SpanContext remoteParent) { - Span currentSpan = TracingContextUtils.getCurrentSpan(); switch (parentType) { case NO_PARENT: return null; - case CURRENT_SPAN: - return currentSpan != null ? currentSpan.getContext() : null; + case CURRENT_CONTEXT: + return TracingContextUtils.getCurrentSpan().getContext(); case EXPLICIT_PARENT: return explicitParent.getContext(); case EXPLICIT_REMOTE_PARENT: @@ -277,8 +277,8 @@ private static SpanContext parent( @Nullable private static Span parentSpan(ParentType parentType, Span explicitParent) { switch (parentType) { - case CURRENT_SPAN: - return TracingContextUtils.getCurrentSpan(); + case CURRENT_CONTEXT: + return TracingContextUtils.getSpanWithoutDefault(Context.current()); case EXPLICIT_PARENT: return explicitParent; default: @@ -287,7 +287,7 @@ private static Span parentSpan(ParentType parentType, Span explicitParent) { } private enum ParentType { - CURRENT_SPAN, + CURRENT_CONTEXT, EXPLICIT_PARENT, EXPLICIT_REMOTE_PARENT, NO_PARENT, 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 bab1dc39dbb..8fa0d3e0caa 100644 --- a/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdk.java +++ b/sdk/src/main/java/io/opentelemetry/sdk/trace/TracerSdk.java @@ -17,18 +17,14 @@ package io.opentelemetry.sdk.trace; import io.opentelemetry.context.Scope; -import io.opentelemetry.context.propagation.HttpTextFormat; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.trace.DefaultTracer; import io.opentelemetry.trace.Span; -import io.opentelemetry.trace.SpanContext; import io.opentelemetry.trace.Tracer; import io.opentelemetry.trace.TracingContextUtils; -import io.opentelemetry.trace.propagation.HttpTraceContext; /** {@link TracerSdk} is SDK implementation of {@link Tracer}. */ public final class TracerSdk implements Tracer { - private static final HttpTextFormat HTTP_TEXT_FORMAT = new HttpTraceContext(); private final TracerSharedState sharedState; private final InstrumentationLibraryInfo instrumentationLibraryInfo; @@ -62,11 +58,6 @@ public Span.Builder spanBuilder(String spanName) { sharedState.getClock()); } - @Override - public HttpTextFormat getHttpTextFormat() { - return HTTP_TEXT_FORMAT; - } - /** * Returns the instrumentation library specified when creating the tracer using {@link * TracerSdkProvider}. diff --git a/sdk/src/test/java/io/opentelemetry/sdk/trace/TracerSdkTest.java b/sdk/src/test/java/io/opentelemetry/sdk/trace/TracerSdkTest.java index f51f4f885c7..1650a83763e 100644 --- a/sdk/src/test/java/io/opentelemetry/sdk/trace/TracerSdkTest.java +++ b/sdk/src/test/java/io/opentelemetry/sdk/trace/TracerSdkTest.java @@ -24,7 +24,6 @@ import io.opentelemetry.trace.DefaultSpan; import io.opentelemetry.trace.Span; import io.opentelemetry.trace.TracingContextUtils; -import io.opentelemetry.trace.propagation.HttpTraceContext; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -66,11 +65,6 @@ public void defaultSpanBuilder() { assertThat(tracer.spanBuilder(SPAN_NAME)).isInstanceOf(SpanBuilderSdk.class); } - @Test - public void defaultHttpTextFormat() { - assertThat(tracer.getHttpTextFormat()).isInstanceOf(HttpTraceContext.class); - } - @Test public void getCurrentSpan() { assertThat(tracer.getCurrentSpan()).isInstanceOf(DefaultSpan.class); diff --git a/sdk_contrib/testbed/src/test/java/io/opentelemetry/sdk/contrib/trace/testbed/clientserver/Client.java b/sdk_contrib/testbed/src/test/java/io/opentelemetry/sdk/contrib/trace/testbed/clientserver/Client.java index 7270054bdb2..cf8a30e1e15 100644 --- a/sdk_contrib/testbed/src/test/java/io/opentelemetry/sdk/contrib/trace/testbed/clientserver/Client.java +++ b/sdk_contrib/testbed/src/test/java/io/opentelemetry/sdk/contrib/trace/testbed/clientserver/Client.java @@ -16,6 +16,8 @@ package io.opentelemetry.sdk.contrib.trace.testbed.clientserver; +import io.grpc.Context; +import io.opentelemetry.OpenTelemetry; import io.opentelemetry.context.Scope; import io.opentelemetry.context.propagation.HttpTextFormat.Setter; import io.opentelemetry.trace.Span; @@ -40,10 +42,10 @@ public void send() throws InterruptedException { span.setAttribute("component", "example-client"); try (Scope ignored = tracer.withSpan(span)) { - tracer + OpenTelemetry.getPropagators() .getHttpTextFormat() .inject( - span.getContext(), + Context.current(), message, new Setter() { @Override diff --git a/sdk_contrib/testbed/src/test/java/io/opentelemetry/sdk/contrib/trace/testbed/clientserver/Server.java b/sdk_contrib/testbed/src/test/java/io/opentelemetry/sdk/contrib/trace/testbed/clientserver/Server.java index c4777b152ff..3e453f054bb 100644 --- a/sdk_contrib/testbed/src/test/java/io/opentelemetry/sdk/contrib/trace/testbed/clientserver/Server.java +++ b/sdk_contrib/testbed/src/test/java/io/opentelemetry/sdk/contrib/trace/testbed/clientserver/Server.java @@ -16,12 +16,15 @@ package io.opentelemetry.sdk.contrib.trace.testbed.clientserver; +import io.grpc.Context; +import io.opentelemetry.OpenTelemetry; import io.opentelemetry.context.Scope; import io.opentelemetry.context.propagation.HttpTextFormat.Getter; import io.opentelemetry.trace.Span; import io.opentelemetry.trace.Span.Kind; import io.opentelemetry.trace.SpanContext; import io.opentelemetry.trace.Tracer; +import io.opentelemetry.trace.TracingContextUtils; import java.util.concurrent.ArrayBlockingQueue; import javax.annotation.Nullable; @@ -36,10 +39,11 @@ public Server(ArrayBlockingQueue queue, Tracer tracer) { } private void process(Message message) { - SpanContext context = - tracer + Context context = + OpenTelemetry.getPropagators() .getHttpTextFormat() .extract( + Context.current(), message, new Getter() { @Nullable @@ -48,8 +52,9 @@ public String get(Message carrier, String key) { return carrier.get(key); } }); + SpanContext spanContext = TracingContextUtils.getSpan(context).getContext(); Span span = - tracer.spanBuilder("receive").setSpanKind(Kind.SERVER).setParent(context).startSpan(); + tracer.spanBuilder("receive").setSpanKind(Kind.SERVER).setParent(spanContext).startSpan(); span.setAttribute("component", "example-server"); try (Scope ignored = tracer.withSpan(span)) {