Skip to content

Commit

Permalink
Context propagation update (OTEP 66) (#720)
Browse files Browse the repository at this point in the history
* 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 <giovanni.liva@dynatrace.com>

* 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 <giovanni.liva@dynatrace.com>
  • Loading branch information
carlosalberto and thisthat authored Mar 20, 2020
1 parent 6f0c44a commit 690651b
Show file tree
Hide file tree
Showing 30 changed files with 774 additions and 324 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -69,7 +72,9 @@ public void set(Map<String, String> carrier, String key, String value) {
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 1)
public Map<String, String> measureInject() {
httpTraceContext.inject(contextToTest, carrier, setter);
Context context =
TracingContextUtils.withSpan(DefaultSpan.create(contextToTest), Context.current());
httpTraceContext.inject(context, carrier, setter);
return carrier;
}

Expand Down
36 changes: 36 additions & 0 deletions api/src/main/java/io/opentelemetry/OpenTelemetry.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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}.
*
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package io.opentelemetry.correlationcontext;

import io.opentelemetry.context.Scope;
import io.opentelemetry.context.propagation.HttpTextFormat;
import javax.annotation.concurrent.ThreadSafe;

/**
Expand Down Expand Up @@ -63,53 +62,4 @@ public interface CorrelationContextManager {
* @since 0.1.0
*/
Scope withContext(CorrelationContext distContext);

/**
* Returns the {@link HttpTextFormat} for this implementation.
*
* <p>Usually this will be the W3C Correlation Context as the HTTP text format. For more details,
* see <a href="https://github.com/w3c/correlation-context">correlation-context</a>.
*
* <p>Example of usage on the client:
*
* <pre>{@code
* private static final CorrelationContextManager contextManager =
* OpenTelemetry.getCorrelationContextManager();
* private static final HttpTextFormat textFormat = contextManager.getHttpTextFormat();
*
* private static final HttpTextFormat.Setter setter =
* new HttpTextFormat.Setter<HttpURLConnection>() {
* 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.
* }
* }</pre>
*
* <p>Example of usage on the server:
*
* <pre>{@code
* private static final CorrelationContextManager contextManager =
* OpenTelemetry.getCorrelationContextManager();
* private static final HttpTextFormat textFormat = contextManager.getHttpTextFormat();
* private static final HttpTextFormat.Getter<HttpRequest> getter = ...;
*
* void onRequestReceived(HttpRequest request) {
* CorrelationContext distContext = textFormat.extract(request, getter);
* try (Scope s = contextManager.withContext(distContext)) {
* // Handle request and send response back.
* }
* }
* }</pre>
*
* @return the {@code HttpTextFormat} for this implementation.
* @since 0.1.0
*/
HttpTextFormat<CorrelationContext> getHttpTextFormat();
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -33,8 +30,6 @@
public final class DefaultCorrelationContextManager implements CorrelationContextManager {
private static final DefaultCorrelationContextManager INSTANCE =
new DefaultCorrelationContextManager();
private static final HttpTextFormat<CorrelationContext> HTTP_TEXT_FORMAT =
new NoopHttpTextFormat();

/**
* Returns a {@code CorrelationContextManager} singleton that is the default implementation for
Expand Down Expand Up @@ -62,11 +57,6 @@ public Scope withContext(CorrelationContext distContext) {
return CorrelationsContextUtils.currentContextWith(distContext);
}

@Override
public HttpTextFormat<CorrelationContext> getHttpTextFormat() {
return HTTP_TEXT_FORMAT;
}

@Immutable
private static final class NoopCorrelationContextBuilder implements CorrelationContext.Builder {
@Override
Expand All @@ -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;
}

Expand All @@ -100,26 +90,4 @@ public CorrelationContext build() {
return EmptyCorrelationContext.getInstance();
}
}

@Immutable
private static final class NoopHttpTextFormat implements HttpTextFormat<CorrelationContext> {
@Override
public List<String> fields() {
return Collections.emptyList();
}

@Override
public <C> void inject(CorrelationContext distContext, C carrier, Setter<C> setter) {
Utils.checkNotNull(distContext, "distContext");
Utils.checkNotNull(carrier, "carrier");
Utils.checkNotNull(setter, "setter");
}

@Override
public <C> CorrelationContext extract(C carrier, Getter<C> getter) {
Utils.checkNotNull(carrier, "carrier");
Utils.checkNotNull(getter, "getter");
return EmptyCorrelationContext.getInstance();
}
}
}
23 changes: 7 additions & 16 deletions api/src/main/java/io/opentelemetry/trace/DefaultTracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -32,7 +31,6 @@
@ThreadSafe
public final class DefaultTracer implements Tracer {
private static final DefaultTracer INSTANCE = new DefaultTracer();
private static final HttpTextFormat<SpanContext> HTTP_TEXT_FORMAT = new HttpTraceContext();

/**
* Returns a {@code Tracer} singleton that is the default implementations for {@link Tracer}.
Expand All @@ -56,30 +54,24 @@ public Scope withSpan(Span span) {

@Override
public Span.Builder spanBuilder(String spanName) {
return NoopSpanBuilder.create(this, spanName);
}

@Override
public HttpTextFormat<SpanContext> 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)
Expand Down Expand Up @@ -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;
}
}
}
57 changes: 0 additions & 57 deletions api/src/main/java/io/opentelemetry/trace/Tracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -152,59 +150,4 @@ public interface Tracer {
* @since 0.1.0
*/
Span.Builder spanBuilder(String spanName);

/**
* Returns the {@link HttpTextFormat} for this tracer implementation.
*
* <p>If no tracer implementation is provided, this defaults to the W3C Trace Context HTTP text
* format ({@link HttpTraceContext}). For more details see <a
* href="https://w3c.github.io/trace-context/">W3C Trace Context</a>.
*
* <p>Example of usage on the client:
*
* <pre>{@code
* private static final Tracer tracer = OpenTelemetry.getTracer();
* private static final HttpTextFormat textFormat = tracer.getHttpTextFormat();
* private static final HttpTextFormat.Setter setter =
* new HttpTextFormat.Setter<HttpURLConnection>() {
* 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.
* }
* }</pre>
*
* <p>Example of usage on the server:
*
* <pre>{@code
* private static final Tracer tracer = OpenTelemetry.getTracer();
* private static final HttpTextFormat textFormat = tracer.getHttpTextFormat();
* private static final HttpTextFormat.Getter<HttpRequest> 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()
* }
* }</pre>
*
* @return the {@code HttpTextFormat} for this implementation.
* @since 0.1.0
*/
HttpTextFormat<SpanContext> getHttpTextFormat();
}
Loading

0 comments on commit 690651b

Please sign in to comment.