Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Context propagation update (OTEP 66) #720

Merged
merged 47 commits into from
Mar 20, 2020
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
e2f642b
Initial Propagators refactor.
carlosalberto Dec 16, 2019
d5d3e02
Add tests for the new propagators changes.
carlosalberto Dec 17, 2019
b60b02d
Make the SDK compile/pass.
carlosalberto Dec 17, 2019
9160417
Make the OT shim compile/pass.
carlosalberto Dec 17, 2019
b97d700
Make contrib components compile/pass.
carlosalberto Dec 17, 2019
0b109f9
Improvement over Span/SpanContext handling in Context.
carlosalberto Dec 18, 2019
51732a9
Add Span.setParent(Context) overload.
carlosalberto Dec 19, 2019
d6894d4
Do not provide default values for Span/SpanContext keys in Context.
carlosalberto Dec 19, 2019
d5acde5
Improve the Context's active state handling.
carlosalberto Dec 19, 2019
71f04d4
Rename DistributedContext to CorrelationContext.
carlosalberto Dec 19, 2019
eb1e411
Improve names for correlationcontext's ContextUtils methods.
carlosalberto Dec 19, 2019
bbfa035
Don't provide an automatic default for current CorrelationContext.
carlosalberto Dec 19, 2019
b9f9b93
Improve the client-server example after the recent changes.
carlosalberto Dec 19, 2019
fdf644b
Adds CorrelationContext.Builder.setParent(Context) overload.
carlosalberto Dec 20, 2019
fd2b4a9
s/be/become.
carlosalberto Dec 20, 2019
24fecd1
Fix javadoc.
carlosalberto Dec 20, 2019
3f7c227
Merge branch 'master' into context_prop_update
carlosalberto Jan 9, 2020
b56ac60
No need to use diamond.
carlosalberto Jan 9, 2020
08297c6
Simply import withScopedContext().
carlosalberto Jan 9, 2020
be3dd73
Merge branch 'master' into context_prop_update
carlosalberto Jan 22, 2020
e06c32f
Fix the API/SDK build.
carlosalberto Jan 24, 2020
4c48266
Remove the builder from the Propagators interface.
carlosalberto Jan 24, 2020
1328ec5
Fix name.
carlosalberto Jan 24, 2020
d35f19e
Use Collections.emptyList() directly.
carlosalberto Jan 24, 2020
14acd5c
Rename Propagators to ContextPropagators.
carlosalberto Jan 24, 2020
b0649da
Move context/ members in api/ to context_prop/
carlosalberto Feb 20, 2020
762408e
Add check/tests for null scoped Contexts.
carlosalberto Feb 20, 2020
05b7628
Rename ContextUtils classes to better alternatives.
carlosalberto Feb 21, 2020
1113f61
Update the context* util classes.
carlosalberto Mar 9, 2020
d271bb6
Merge branch 'master' into context_prop_update
carlosalberto Mar 10, 2020
43e42d4
Make the code compile after the latest master merge.
carlosalberto Mar 10, 2020
014b3c4
Cache the fields() in our default composite propagator.
carlosalberto Mar 10, 2020
f3d29a3
Remove the overloads of setParent(Context) for now.
carlosalberto Mar 10, 2020
555095b
Use DefaultSpan for the tests instead of calling getTracerProvider()
carlosalberto Mar 10, 2020
3c1f781
Fix the sdk testbed artifact build.
carlosalberto Mar 10, 2020
64b5b1e
Merge branch 'master' into context_prop_update
carlosalberto Mar 13, 2020
136f0aa
Make the B3 propagator comply with the new propagator API.
carlosalberto Mar 14, 2020
ddc370a
Simplify the HttpTraceContextTest tests.
carlosalberto Mar 14, 2020
a1d93ec
Simplify the ContextUtils* classes handling of default values.
carlosalberto Mar 14, 2020
3c96627
Minor nit.
carlosalberto Mar 14, 2020
5f820cd
Merge branch 'master' into context_prop_update
carlosalberto Mar 15, 2020
9a1eb5b
Update api/src/main/java/io/opentelemetry/OpenTelemetry.java
carlosalberto Mar 17, 2020
268b546
Annotate ContextPropagators with ThreadSafe instead of Immutable.
carlosalberto Mar 19, 2020
a0ec628
Do not use the fully qualified ContextUtils identifier.
carlosalberto Mar 19, 2020
7a3cbeb
Remove SpanContext support from TracingContextUtils.
carlosalberto Mar 20, 2020
88fdcbb
Rever to using non-defaulted key for TracingContextUtils.
carlosalberto Mar 20, 2020
37ba00b
Revert the default keys for CorrelationsContextUtils.
carlosalberto Mar 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,9 +16,12 @@

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.spi.CorrelationContextManagerProvider;
import io.opentelemetry.internal.Utils;
import io.opentelemetry.metrics.DefaultMeterRegistry;
import io.opentelemetry.metrics.DefaultMeterRegistryProvider;
import io.opentelemetry.metrics.Meter;
Expand All @@ -28,6 +31,7 @@
import io.opentelemetry.trace.DefaultTracerRegistryProvider;
import io.opentelemetry.trace.Tracer;
import io.opentelemetry.trace.TracerRegistry;
import io.opentelemetry.trace.propagation.HttpTraceContext;
import io.opentelemetry.trace.spi.TracerRegistryProvider;
import java.util.ServiceLoader;
import javax.annotation.Nullable;
Expand All @@ -52,6 +56,9 @@ public final class OpenTelemetry {
private final MeterRegistry meterRegistry;
private final CorrelationContextManager contextManager;

private volatile ContextPropagators propagators =
DefaultContextPropagators.builder().addHttpTextFormat(new HttpTraceContext()).build();

/**
* Returns a singleton {@link TracerRegistry}.
*
Expand Down Expand Up @@ -89,6 +96,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 {@code HttpTraceContext} registered.
carlosalberto marked this conversation as resolved.
Show resolved Hide resolved
* @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
@@ -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.Immutable;

/**
* A container of the registered propagators for every supported format.
*
* <p>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.
*
* <p>Example of usage on the client:
*
* <pre>{@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<String, String> map = new HashMap<>();
* httpTextFormat.inject(Context.current(), map, new Setter<String, String>() {
* public void put(Map<String, String> map, String key, String value) {
* map.put(key, value);
* }
* });
* // Send the request including the text map and wait for the response.
* }
* }
* }</pre>
*
* <p>Example of usage in the server:
*
* <pre>{@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<String, String>() {
* 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();
* }
* }
* }</pre>
*
* @since 0.3.0
*/
@Immutable
public interface ContextPropagators {
carlosalberto marked this conversation as resolved.
Show resolved Hide resolved

/**
* Returns a {@link HttpTextFormat} propagator.
*
* <p>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();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* 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;
carlosalberto marked this conversation as resolved.
Show resolved Hide resolved
import io.opentelemetry.context.Scope;
import javax.annotation.concurrent.Immutable;

/**
* Util methods/functionality to interact with the {@link io.grpc.Context}.
*
* <p>Users must interact with the current Context via the public APIs and avoid accessing this
* class directly.
*
* @since 0.1.0
*/
@Immutable
public final class ContextUtils {
/**
* Sets the specified {@code Context} as {@code Context.current()}, returning a {@link Scope} to
* end its active state and restore the previous active {@code Context}.
*
* @param context the {@code Context} to be set as {@code Context.current()}.
* @return the {@link Scope} for the updated {@code Context}.
* @since 0.1.0
*/
public static Scope withScopedContext(Context context) {
return new ContextInScope(context);
}

private static final class ContextInScope implements Scope {
private final Context context;
private final Context previous;

public ContextInScope(Context context) {
this.context = context;
this.previous = context.attach();
}

@Override
public void close() {
context.detach(previous);
}
}

private ContextUtils() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
* 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 io.opentelemetry.internal.Utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* {@code DefaultContextPropagators} is the default, built-in implementation of {@link
* ContextPropagators}.
*
* <p>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.
*
* <p>This is a example of a {@code ContextPropagators} object being created:
*
* <pre>{@code
* ContextPropagators propagators = DefaultContextPropagators.builder()
* .addHttpTextFormat(new HttpTraceContext())
* .addHttpTextFormat(new HttpCorrelationContext())
* .addHttpTextFormat(new MyCustomContextPropagator())
* .build();
* }</pre>
*
* @since 0.3.0
*/
public static final class Builder {
List<HttpTextFormat> textPropagators = new ArrayList<>();

/**
* Adds a {@link HttpTextFormat} propagator.
*
* <p>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) {
Utils.checkNotNull(textFormat, "textFormat");
carlosalberto marked this conversation as resolved.
Show resolved Hide resolved
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 MultiHttpTextFormat(List<HttpTextFormat> textPropagators) {
this.textPropagators = new HttpTextFormat[textPropagators.size()];
textPropagators.toArray(this.textPropagators);
}

@Override
public List<String> fields() {
List<String> fields = new ArrayList<>();
carlosalberto marked this conversation as resolved.
Show resolved Hide resolved
for (int i = 0; i < textPropagators.length; i++) {
fields.addAll(textPropagators[i].fields());
}

return fields;
}

@Override
public <C> void inject(Context context, C carrier, Setter<C> setter) {
for (int i = 0; i < textPropagators.length; i++) {
textPropagators[i].inject(context, carrier, setter);
}
}

@Override
public <C> Context extract(Context context, C carrier, Getter<C> 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<String> fields() {
return Collections.emptyList();
}

@Override
public <C> void inject(Context context, C carrier, Setter<C> setter) {}

@Override
public <C> Context extract(Context context, C carrier, Getter<C> getter) {
return context;
}
}
}
Loading