Add a ContextValue interface to allow Context.withValue(value) withou… (#1827)

* Add a ContextValue interface to allow Context.withValue(value) without a key.

* Assertions

* Renames
This commit is contained in:
Anuraag Agrawal 2020-10-21 11:26:54 +09:00 committed by GitHub
parent 17ef49abf7
commit ecdfc391f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 84 additions and 62 deletions

View File

@ -11,7 +11,6 @@ import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.SpanContext;
import io.opentelemetry.trace.TraceFlags;
import io.opentelemetry.trace.TraceState;
import io.opentelemetry.trace.TracingContextUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -75,7 +74,7 @@ public class HttpTraceContextInjectBenchmark {
private static List<Context> createContexts(List<SpanContext> spanContexts) {
List<Context> contexts = new ArrayList<>();
for (SpanContext context : spanContexts) {
contexts.add(TracingContextUtils.withSpan(Span.wrap(context), Context.root()));
contexts.add(Context.root().with(Span.wrap(context)));
}
return contexts;
}

View File

@ -8,6 +8,7 @@ package io.opentelemetry.trace;
import io.opentelemetry.common.AttributeKey;
import io.opentelemetry.common.Attributes;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.ImplicitContextKeyed;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
@ -19,7 +20,7 @@ import javax.annotation.concurrent.ThreadSafe;
* <p>{@code Span} <b>must</b> be ended by calling {@link #end()}.
*/
@ThreadSafe
public interface Span {
public interface Span extends ImplicitContextKeyed {
/**
* Returns an invalid {@link Span}. An invalid {@link Span} is used when tracing is disabled,
@ -286,6 +287,11 @@ public interface Span {
*/
boolean isRecording();
@Override
default Context storeInContext(Context context) {
return TracingContextUtils.withSpan(this, context);
}
/**
* {@link Builder} is used to construct {@link Span} instances which define arbitrary scopes of
* code that are sampled for distributed tracing as a single atomic unit.

View File

@ -25,7 +25,7 @@ public final class TracingContextUtils {
* @param context the parent {@code Context}.
* @return a new context with the given value set.
*/
public static Context withSpan(Span span, Context context) {
static Context withSpan(Span span, Context context) {
return context.withValues(CONTEXT_SPAN_KEY, span);
}
@ -87,7 +87,7 @@ public final class TracingContextUtils {
*/
@MustBeClosed
public static Scope currentContextWith(Span span) {
return withSpan(span, io.opentelemetry.context.Context.current()).makeCurrent();
return Context.current().with(span).makeCurrent();
}
private TracingContextUtils() {}

View File

@ -149,7 +149,7 @@ public class HttpTraceContext implements TextMapPropagator {
return context;
}
return TracingContextUtils.withSpan(Span.wrap(spanContext), context);
return context.with(Span.wrap(spanContext));
}
private static <C> SpanContext extractImpl(C carrier, Getter<C> getter) {

View File

@ -43,7 +43,7 @@ class DefaultTracerTest {
Span span =
defaultTracer
.spanBuilder(SPAN_NAME)
.setParent(TracingContextUtils.withSpan(Span.wrap(spanContext), Context.root()))
.setParent(Context.root().with(Span.wrap(spanContext)))
.startSpan();
assertThat(span.getContext()).isSameAs(spanContext);
}
@ -53,10 +53,7 @@ class DefaultTracerTest {
Span parent = Span.wrap(spanContext);
Span span =
defaultTracer
.spanBuilder(SPAN_NAME)
.setParent(TracingContextUtils.withSpan(parent, Context.root()))
.startSpan();
defaultTracer.spanBuilder(SPAN_NAME).setParent(Context.root().with(parent)).startSpan();
assertThat(span.getContext()).isSameAs(spanContext);
}
@ -74,7 +71,7 @@ class DefaultTracerTest {
@Test
void testSpanContextPropagation_fromContext() {
Context context = TracingContextUtils.withSpan(Span.wrap(spanContext), Context.current());
Context context = Context.current().with(Span.wrap(spanContext));
Span span = defaultTracer.spanBuilder(SPAN_NAME).setParent(context).startSpan();
assertThat(span.getContext()).isSameAs(spanContext);
@ -82,7 +79,7 @@ class DefaultTracerTest {
@Test
void testSpanContextPropagation_fromContextAfterNoParent() {
Context context = TracingContextUtils.withSpan(Span.wrap(spanContext), Context.current());
Context context = Context.current().with(Span.wrap(spanContext));
Span span = defaultTracer.spanBuilder(SPAN_NAME).setNoParent().setParent(context).startSpan();
assertThat(span.getContext()).isSameAs(spanContext);
@ -90,7 +87,7 @@ class DefaultTracerTest {
@Test
void testSpanContextPropagation_fromContextThenNoParent() {
Context context = TracingContextUtils.withSpan(Span.wrap(spanContext), Context.current());
Context context = Context.current().with(Span.wrap(spanContext));
Span span = defaultTracer.spanBuilder(SPAN_NAME).setParent(context).setNoParent().startSpan();
assertThat(span.getContext()).isEqualTo(SpanContext.getInvalid());

View File

@ -22,7 +22,7 @@ class SpanBuilderTest {
void doNotCrash_NoopImplementation() {
Span.Builder spanBuilder = tracer.spanBuilder("MySpanName");
spanBuilder.setSpanKind(Kind.SERVER);
spanBuilder.setParent(TracingContextUtils.withSpan(Span.wrap(null), Context.root()));
spanBuilder.setParent(Context.root().with(Span.wrap(null)));
spanBuilder.setParent(Context.root());
spanBuilder.setNoParent();
spanBuilder.addLink(Span.getInvalid().getContext());

View File

@ -21,7 +21,7 @@ class TracingContextUtilsTest {
@Test
void testGetCurrentSpan_SetSpan() {
Span span = Span.wrap(SpanContext.getInvalid());
try (Scope ignored = TracingContextUtils.withSpan(span, Context.current()).makeCurrent()) {
try (Scope ignored = Context.current().with(span).makeCurrent()) {
assertThat(TracingContextUtils.getCurrentSpan()).isSameAs(span);
}
}
@ -35,7 +35,7 @@ class TracingContextUtilsTest {
@Test
void testGetSpan_ExplicitContext() {
Span span = Span.wrap(SpanContext.getInvalid());
Context context = TracingContextUtils.withSpan(span, Context.current());
Context context = Context.current().with(span);
assertThat(TracingContextUtils.getSpan(context)).isSameAs(span);
}
@ -48,7 +48,7 @@ class TracingContextUtilsTest {
@Test
void testGetSpanWithoutDefault_ExplicitContext() {
Span span = Span.wrap(SpanContext.getInvalid());
Context context = TracingContextUtils.withSpan(span, Context.current());
Context context = Context.current().with(span);
assertThat(TracingContextUtils.getSpanWithoutDefault(context)).isSameAs(span);
}

View File

@ -52,7 +52,7 @@ class HttpTraceContextTest {
}
private static Context withSpanContext(SpanContext spanContext, Context context) {
return TracingContextUtils.withSpan(Span.wrap(spanContext), context);
return context.with(Span.wrap(spanContext));
}
@Test

View File

@ -155,6 +155,11 @@ public interface Context {
return withValues(k1, v1, k2, v2, k3, v3).withValues(k4, v4);
}
/** Returns a new {@link Context} with the given {@link ImplicitContextKeyed} set. */
default Context with(ImplicitContextKeyed value) {
return value.storeInContext(this);
}
/**
* Makes this the {@linkplain Context#current() current context} and returns a {@link Scope} which
* corresponds to the scope of execution this context is current for. {@link Context#current()}

View File

@ -0,0 +1,25 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.context;
/**
* A value that can be stored inside {@link Context}. Types will generally use this interface to
* allow storing themselves in {@link Context} without exposing a {@link ContextKey}.
*/
public interface ImplicitContextKeyed {
/**
* Returns a new {@link Context} created by setting {@code this} into the provided {@link
* Context}. It is generally recommended to call {@link Context#with(ImplicitContextKeyed)}
* instead of this method. The following are equivalent.
*
* <ul>
* <li>{@code context.with(myContextValue)}
* <li>{@code myContextValue.storeInContext(context)}
* </ul>
*/
Context storeInContext(Context context);
}

View File

@ -11,7 +11,6 @@ import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.SpanContext;
import io.opentelemetry.trace.TraceFlags;
import io.opentelemetry.trace.TraceState;
import io.opentelemetry.trace.TracingContextUtils;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@ -62,7 +61,7 @@ public class PropagatorContextInjectBenchmark {
@BenchmarkMode(Mode.AverageTime)
@Fork(1)
public Map<String, String> measureInject() {
Context context = TracingContextUtils.withSpan(Span.wrap(contextToTest), Context.current());
Context context = Context.current().with(Span.wrap(contextToTest));
doInject(context, carrier);
return carrier;
}

View File

@ -126,7 +126,7 @@ public class AwsXRayPropagator implements TextMapPropagator {
return context;
}
return TracingContextUtils.withSpan(Span.wrap(spanContext), context);
return context.with(Span.wrap(spanContext));
}
private static <C> SpanContext getSpanContextFromHeader(C carrier, Getter<C> getter) {

View File

@ -13,7 +13,6 @@ import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.SpanContext;
import io.opentelemetry.trace.TracingContextUtils;
import java.util.Objects;
import java.util.Optional;
import java.util.logging.Logger;
@ -34,7 +33,7 @@ final class B3PropagatorExtractorMultipleHeaders implements B3PropagatorExtracto
return Optional.empty();
}
return Optional.of(TracingContextUtils.withSpan(Span.wrap(spanContext), context));
return Optional.of(context.with(Span.wrap(spanContext)));
}
private static <C> SpanContext getSpanContextFromMultipleHeaders(

View File

@ -12,7 +12,6 @@ import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.SpanContext;
import io.opentelemetry.trace.TracingContextUtils;
import java.util.Objects;
import java.util.Optional;
import java.util.logging.Logger;
@ -33,7 +32,7 @@ final class B3PropagatorExtractorSingleHeader implements B3PropagatorExtractor {
return Optional.empty();
}
return Optional.of(TracingContextUtils.withSpan(Span.wrap(spanContext), context));
return Optional.of(context.with(Span.wrap(spanContext)));
}
@SuppressWarnings("StringSplitter")

View File

@ -118,7 +118,7 @@ public class JaegerPropagator implements TextMapPropagator {
return context;
}
return TracingContextUtils.withSpan(Span.wrap(spanContext), context);
return context.with(Span.wrap(spanContext));
}
@SuppressWarnings("StringSplitter")

View File

@ -81,7 +81,7 @@ public class OtTracerPropagator implements TextMapPropagator {
if (!spanContext.isValid()) {
return context;
}
return TracingContextUtils.withSpan(Span.wrap(spanContext), context);
return context.with(Span.wrap(spanContext));
}
static SpanContext buildSpanContext(String traceId, String spanId, String sampled) {

View File

@ -244,7 +244,7 @@ class AwsXRayPropagatorTest {
}
private static Context withSpanContext(SpanContext spanContext, Context context) {
return TracingContextUtils.withSpan(Span.wrap(spanContext), context);
return context.with(Span.wrap(spanContext));
}
private static SpanContext getSpanContext(Context context) {

View File

@ -54,7 +54,7 @@ class B3PropagatorTest {
}
private static Context withSpanContext(SpanContext spanContext, Context context) {
return TracingContextUtils.withSpan(Span.wrap(spanContext), context);
return context.with(Span.wrap(spanContext));
}
@Test

View File

@ -64,7 +64,7 @@ class JaegerPropagatorTest {
}
private static Context withSpanContext(SpanContext spanContext, Context context) {
return TracingContextUtils.withSpan(Span.wrap(spanContext), context);
return context.with(Span.wrap(spanContext));
}
@Test

View File

@ -40,7 +40,7 @@ class OtTracerPropagatorTest {
}
private static Context withSpanContext(SpanContext spanContext, Context context) {
return TracingContextUtils.withSpan(Span.wrap(spanContext), context);
return context.with(Span.wrap(spanContext));
}
@Test

View File

@ -6,7 +6,6 @@
package io.opentelemetry.extensions.trace.propagation;
import static io.opentelemetry.trace.TracingContextUtils.getSpan;
import static io.opentelemetry.trace.TracingContextUtils.withSpan;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.verify;
@ -111,7 +110,7 @@ class TraceMultiPropagatorTest {
.build();
Map<String, String> carrier = new HashMap<>();
prop.inject(withSpan(SPAN, Context.current()), carrier, Map::put);
prop.inject(Context.current().with(SPAN), carrier, Map::put);
assertThat(getSpan(PROPAGATOR1.extract(Context.current(), carrier, Map::get)).getContext())
.isEqualTo(SPAN.getContext());
@ -141,7 +140,7 @@ class TraceMultiPropagatorTest {
.build();
Map<String, String> carrier = new HashMap<>();
PROPAGATOR2.inject(withSpan(SPAN, Context.current()), carrier, Map::put);
PROPAGATOR2.inject(Context.current().with(SPAN), carrier, Map::put);
assertThat(getSpan(prop.extract(Context.current(), carrier, Map::get)).getContext())
.isEqualTo(SPAN.getContext());
}
@ -151,7 +150,7 @@ class TraceMultiPropagatorTest {
TextMapPropagator prop = TraceMultiPropagator.builder().addPropagator(PROPAGATOR1).build();
Map<String, String> carrier = new HashMap<>();
PROPAGATOR3.inject(withSpan(SPAN, Context.current()), carrier, Map::put);
PROPAGATOR3.inject(Context.current().with(SPAN), carrier, Map::put);
assertThat(prop.extract(Context.current(), carrier, Map::get)).isEqualTo(Context.current());
}
@ -165,7 +164,7 @@ class TraceMultiPropagatorTest {
.build();
Map<String, String> carrier = new HashMap<>();
PROPAGATOR3.inject(withSpan(SPAN, Context.current()), carrier, Map::put);
PROPAGATOR3.inject(Context.current().with(SPAN), carrier, Map::put);
assertThat(getSpan(prop.extract(Context.current(), carrier, Map::get)).getContext())
.isEqualTo(SPAN.getContext());
verify(mockPropagator).fields();

View File

@ -9,7 +9,6 @@ import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.StatusCode;
import io.opentelemetry.trace.TracingContextUtils;
import java.util.concurrent.Callable;
/** Util methods/functionality to interact with the {@link Span} in the {@link Context}. */
@ -55,7 +54,7 @@ public final class CurrentSpanUtils {
@Override
public void run() {
try (Scope ignored = TracingContextUtils.withSpan(span, Context.current()).makeCurrent()) {
try (Scope ignored = Context.current().with(span).makeCurrent()) {
runnable.run();
} catch (Throwable t) {
setErrorStatus(span, t);
@ -86,7 +85,7 @@ public final class CurrentSpanUtils {
@Override
public V call() throws Exception {
try (Scope ignored = TracingContextUtils.withSpan(span, Context.current()).makeCurrent()) {
try (Scope ignored = Context.current().with(span).makeCurrent()) {
return callable.call();
} catch (Exception e) {
setErrorStatus(span, e);

View File

@ -6,8 +6,10 @@
package io.opentelemetry.extensions.trace;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.StatusCode;
@ -18,13 +20,13 @@ import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
/** Unit tests for {@link CurrentSpanUtils}. */
class CurrentSpanUtilsTest {
@Mock private Span span;
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
when(span.storeInContext(any())).thenCallRealMethod();
}
// TODO(bdrutu): When update to junit 4.13 use assertThrows instead of this.
@ -60,7 +62,7 @@ class CurrentSpanUtilsTest {
assertThat(getCurrentSpan()).isSameAs(span);
};
CurrentSpanUtils.withSpan(span, false, runnable).run();
verifyNoInteractions(span);
verify(span, never()).end();
assertThat(getCurrentSpan().getContext().isValid()).isFalse();
}
@ -120,7 +122,7 @@ class CurrentSpanUtilsTest {
return ret;
};
assertThat(CurrentSpanUtils.withSpan(span, false, callable).call()).isEqualTo(ret);
verifyNoInteractions(span);
verify(span, never()).end();
assertThat(getCurrentSpan().getContext().isValid()).isFalse();
}

View File

@ -9,7 +9,6 @@ import com.google.gson.Gson;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.DefaultContextPropagators;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.TracingContextUtils;
import io.opentelemetry.trace.propagation.HttpTraceContext;
import java.util.ArrayList;
import java.util.Enumeration;
@ -83,7 +82,7 @@ public class Application {
.setParent(context)
.startSpan();
Context withSpanContext = TracingContextUtils.withSpan(span, context);
Context withSpanContext = context.with(span);
// Make a new request using the builder
okhttp3.Request.Builder reqBuilder = new okhttp3.Request.Builder();

View File

@ -22,8 +22,7 @@ final class Propagation extends BaseShimObject {
}
public void injectTextMap(SpanContextShim contextShim, TextMapInject carrier) {
Context context =
TracingContextUtils.withSpan(Span.wrap(contextShim.getSpanContext()), Context.current());
Context context = Context.current().with(Span.wrap(contextShim.getSpanContext()));
context = BaggageUtils.withBaggage(contextShim.getBaggage(), context);
propagators().getTextMapPropagator().inject(context, carrier, TextMapSetter.INSTANCE);

View File

@ -15,7 +15,6 @@ import io.opentelemetry.common.AttributeKey;
import io.opentelemetry.context.Context;
import io.opentelemetry.trace.Span.Kind;
import io.opentelemetry.trace.StatusCode;
import io.opentelemetry.trace.TracingContextUtils;
import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.Tracer.SpanBuilder;
@ -183,14 +182,13 @@ final class SpanBuilderShim extends BaseShimObject implements SpanBuilder {
if (ignoreActiveSpan && parentSpan == null && parentSpanContext == null) {
builder.setNoParent();
} else if (parentSpan != null) {
builder.setParent(TracingContextUtils.withSpan(parentSpan.getSpan(), Context.root()));
builder.setParent(Context.root().with(parentSpan.getSpan()));
SpanContextShim contextShim = spanContextTable().get(parentSpan);
baggage = contextShim == null ? null : contextShim.getBaggage();
} else if (parentSpanContext != null) {
builder.setParent(
TracingContextUtils.withSpan(
io.opentelemetry.trace.Span.wrap(parentSpanContext.getSpanContext()),
Context.root()));
Context.root()
.with(io.opentelemetry.trace.Span.wrap(parentSpanContext.getSpanContext())));
baggage = parentSpanContext.getBaggage();
}

View File

@ -647,7 +647,7 @@ class SpanBuilderSdkTest {
void noParent_override() {
final Span parent = tracerSdk.spanBuilder(SPAN_NAME).startSpan();
try {
final Context parentContext = TracingContextUtils.withSpan(parent, Context.current());
final Context parentContext = Context.current().with(parent);
RecordEventsReadableSpan span =
(RecordEventsReadableSpan)
tracerSdk.spanBuilder(SPAN_NAME).setNoParent().setParent(parentContext).startSpan();
@ -659,7 +659,7 @@ class SpanBuilderSdkTest {
assertThat(span.toSpanData().getParentSpanId())
.isEqualTo(parent.getContext().getSpanIdAsHexString());
final Context parentContext2 = TracingContextUtils.withSpan(parent, Context.current());
final Context parentContext2 = Context.current().with(parent);
RecordEventsReadableSpan span2 =
(RecordEventsReadableSpan)
tracerSdk
@ -688,7 +688,7 @@ class SpanBuilderSdkTest {
Span parent = tracerSdk.spanBuilder(SPAN_NAME).startSpan();
try {
final Context parentContext = TracingContextUtils.withSpan(parent, Context.current());
final Context parentContext = Context.current().with(parent);
RecordEventsReadableSpan span =
(RecordEventsReadableSpan)
tracerSdk.spanBuilder(SPAN_NAME).setNoParent().setParent(parentContext).startSpan();
@ -710,7 +710,7 @@ class SpanBuilderSdkTest {
@Test
void parent_fromContext() {
final Span parent = tracerSdk.spanBuilder(SPAN_NAME).startSpan();
final Context context = TracingContextUtils.withSpan(parent, Context.current());
final Context context = Context.current().with(parent);
try {
final RecordEventsReadableSpan span =
(RecordEventsReadableSpan)
@ -783,7 +783,7 @@ class SpanBuilderSdkTest {
void parent_invalidContext() {
Span parent = Span.getInvalid();
final Context parentContext = TracingContextUtils.withSpan(parent, Context.current());
final Context parentContext = Context.current().with(parent);
RecordEventsReadableSpan span =
(RecordEventsReadableSpan)
tracerSdk.spanBuilder(SPAN_NAME).setParent(parentContext).startSpan();

View File

@ -98,10 +98,7 @@ class HandlerTest {
Client client;
Span parentSpan = tracer.spanBuilder("parent").startSpan();
try (Scope ignored = TracingContextUtils.currentContextWith(parentSpan)) {
client =
new Client(
new RequestHandler(
tracer, TracingContextUtils.withSpan(parentSpan, Context.current())));
client = new Client(new RequestHandler(tracer, Context.current().with(parentSpan)));
String response = client.send("correct_parent").get(15, TimeUnit.SECONDS);
assertThat(response).isEqualTo("correct_parent:response");
} finally {