diff --git a/api/src/main/java/io/opentelemetry/OpenTelemetry.java b/api/src/main/java/io/opentelemetry/OpenTelemetry.java index cbce580e7c4..9a7b416bea2 100644 --- a/api/src/main/java/io/opentelemetry/OpenTelemetry.java +++ b/api/src/main/java/io/opentelemetry/OpenTelemetry.java @@ -16,9 +16,12 @@ package io.opentelemetry; -import io.opentelemetry.distributedcontext.DefaultDistributedContextManager; -import io.opentelemetry.distributedcontext.DistributedContextManager; -import io.opentelemetry.distributedcontext.spi.DistributedContextManagerProvider; +import io.opentelemetry.context.propagation.DefaultHttpExtractor; +import io.opentelemetry.context.propagation.DefaultHttpInjector; +import io.opentelemetry.context.propagation.Propagators; +import io.opentelemetry.distributedcontext.CorrelationContextManager; +import io.opentelemetry.distributedcontext.DefaultCorrelationContextManager; +import io.opentelemetry.distributedcontext.spi.CorrelationContextManagerProvider; import io.opentelemetry.metrics.DefaultMeter; import io.opentelemetry.metrics.Meter; import io.opentelemetry.metrics.spi.MeterProvider; @@ -33,13 +36,13 @@ /** * This class provides a static global accessor for telemetry objects {@link Tracer}, {@link Meter} - * and {@link DistributedContextManager}. + * and {@link CorrelationContextManager}. * *

The telemetry objects are lazy-loaded singletons resolved via {@link ServiceLoader} mechanism. * * @see TracerFactory * @see MeterProvider - * @see DistributedContextManagerProvider + * @see CorrelationContextManagerProvider */ @ThreadSafe public final class OpenTelemetry { @@ -48,7 +51,9 @@ public final class OpenTelemetry { private final TracerFactory tracerFactory; private final Meter meter; - private final DistributedContextManager contextManager; + private final CorrelationContextManager contextManager; + private volatile Propagators propagators = + Propagators.create(new DefaultHttpInjector(), new DefaultHttpExtractor()); /** * Returns a singleton {@link TracerFactory}. @@ -74,18 +79,26 @@ public static Meter getMeter() { } /** - * Returns a singleton {@link DistributedContextManager}. + * Returns a singleton {@link CorrelationContextManager}. * * @return registered manager or default via {@link - * DefaultDistributedContextManager#getInstance()}. + * DefaultCorrelationContextManager#getInstance()}. * @throws IllegalStateException if a specified manager (via system properties) could not be * found. * @since 0.1.0 */ - public static DistributedContextManager getDistributedContextManager() { + public static CorrelationContextManager getCorrelationContextManager() { return getInstance().contextManager; } + public static Propagators getPropagators() { + return getInstance().propagators; + } + + public static void setPropagators(Propagators propagators) { + getInstance().propagators = propagators; + } + /** Lazy loads an instance. */ private static OpenTelemetry getInstance() { if (instance == null) { @@ -107,12 +120,12 @@ private OpenTelemetry() { MeterProvider meterProvider = loadSpi(MeterProvider.class); meter = meterProvider != null ? meterProvider.create() : DefaultMeter.getInstance(); - DistributedContextManagerProvider contextManagerProvider = - loadSpi(DistributedContextManagerProvider.class); + CorrelationContextManagerProvider contextManagerProvider = + loadSpi(CorrelationContextManagerProvider.class); contextManager = contextManagerProvider != null ? contextManagerProvider.create() - : DefaultDistributedContextManager.getInstance(); + : DefaultCorrelationContextManager.getInstance(); } /** diff --git a/api/src/main/java/io/opentelemetry/baggage/BaggageManager.java b/api/src/main/java/io/opentelemetry/baggage/BaggageManager.java new file mode 100644 index 00000000000..837cfaaecb7 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/baggage/BaggageManager.java @@ -0,0 +1,35 @@ +/* + * 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.baggage; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.HttpExtractor; +import io.opentelemetry.context.propagation.HttpInjector; + +public interface BaggageManager { + public Context setValue(Context ctx, String key, String value); + + public String getValue(Context ctx, String key); + + public Context removeValue(Context ctx, String key); + + public Context clear(Context ctx); + + public HttpInjector getHttpInjector(); + + public HttpExtractor getHttpExtractor(); +} diff --git a/api/src/main/java/io/opentelemetry/baggage/DefaultBaggageManager.java b/api/src/main/java/io/opentelemetry/baggage/DefaultBaggageManager.java new file mode 100644 index 00000000000..74e43be2425 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/baggage/DefaultBaggageManager.java @@ -0,0 +1,65 @@ +/* + * 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.baggage; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.HttpExtractor; +import io.opentelemetry.context.propagation.HttpInjector; +import javax.annotation.Nullable; + +public final class DefaultBaggageManager implements BaggageManager { + private static final DefaultBaggageManager INSTANCE = new DefaultBaggageManager(); + + public static DefaultBaggageManager getInstance() { + return INSTANCE; + } + + @Override + public Context setValue(Context ctx, String key, String value) { + return ctx; + } + + @Nullable + @Override + public String getValue(Context ctx, String key) { + return null; + } + + @Override + public Context removeValue(Context ctx, String key) { + return ctx; + } + + @Override + public Context clear(Context ctx) { + return ctx; + } + + @Nullable + @Override + public HttpInjector getHttpInjector() { + return null; + } + + @Nullable + @Override + public HttpExtractor getHttpExtractor() { + return null; + } + + // TODO - define noop propagators (expose them?) +} diff --git a/api/src/main/java/io/opentelemetry/baggage/propagation/ContextKeys.java b/api/src/main/java/io/opentelemetry/baggage/propagation/ContextKeys.java new file mode 100644 index 00000000000..155ce88f194 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/baggage/propagation/ContextKeys.java @@ -0,0 +1,29 @@ +/* + * 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.baggage.propagation; + +import io.opentelemetry.context.Context; + +public final class ContextKeys { + private static final Context.Key BAGGAGE_KEY = Context.createKey("baggage"); + + public static Context.Key getSpanContextKey() { + return BAGGAGE_KEY; + } + + private ContextKeys() {} +} diff --git a/api/src/main/java/io/opentelemetry/baggage/propagation/DefaultBaggageExtractor.java b/api/src/main/java/io/opentelemetry/baggage/propagation/DefaultBaggageExtractor.java new file mode 100644 index 00000000000..f52531ee261 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/baggage/propagation/DefaultBaggageExtractor.java @@ -0,0 +1,28 @@ +/* + * 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.baggage.propagation; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.HttpExtractor; + +public final class DefaultBaggageExtractor implements HttpExtractor { + @Override + public Context extract(Context ctx, C carrier, Getter getter) { + // TODO - Implement (outside the bounds of this prototype). + return ctx; + } +} diff --git a/api/src/main/java/io/opentelemetry/baggage/propagation/DefaultBaggageInjector.java b/api/src/main/java/io/opentelemetry/baggage/propagation/DefaultBaggageInjector.java new file mode 100644 index 00000000000..79a5e308d58 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/baggage/propagation/DefaultBaggageInjector.java @@ -0,0 +1,27 @@ +/* + * 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.baggage.propagation; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.HttpInjector; + +public final class DefaultBaggageInjector implements HttpInjector { + @Override + public void inject(Context ctx, C carrier, Setter getter) { + // TODO - Implement (outside the bounds of this prototype). + } +} diff --git a/api/src/main/java/io/opentelemetry/context/Context.java b/api/src/main/java/io/opentelemetry/context/Context.java new file mode 100644 index 00000000000..141b9597312 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/context/Context.java @@ -0,0 +1,72 @@ +/* + * 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; + +public final class Context { + private final io.grpc.Context ctx; + + private Context(io.grpc.Context ctx) { + this.ctx = ctx; + } + + public static Context current() { + return new Context(io.grpc.Context.current()); + } + + public static Scope setCurrent(Context ctx) { + return new ScopeImpl(ctx); + } + + public static Context.Key createKey(String name) { + return new Key(io.grpc.Context.key(name)); + } + + public T getValue(Context.Key key) { + return key.key().get(ctx); + } + + public Context setValue(Context.Key key, T value) { + return new Context(ctx.withValue(key.key(), value)); + } + + public static final class Key { + io.grpc.Context.Key key; + + private Key(io.grpc.Context.Key key) { + this.key = key; + } + + io.grpc.Context.Key key() { + return key; + } + } + + static final class ScopeImpl implements Scope { + private final io.grpc.Context ctx; + private final io.grpc.Context prevCtx; + + public ScopeImpl(Context ctx) { + this.ctx = ctx.ctx; + this.prevCtx = ctx.ctx.attach(); + } + + @Override + public void close() { + ctx.detach(prevCtx); + } + } +} diff --git a/api/src/main/java/io/opentelemetry/context/propagation/ChainedPropagators.java b/api/src/main/java/io/opentelemetry/context/propagation/ChainedPropagators.java new file mode 100644 index 00000000000..4bbdbc6dc3e --- /dev/null +++ b/api/src/main/java/io/opentelemetry/context/propagation/ChainedPropagators.java @@ -0,0 +1,64 @@ +/* + * 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.opentelemetry.context.Context; + +public final class ChainedPropagators { + public static HttpInjector chain(HttpInjector injector1, HttpInjector injector2) { + return new ChainedHttpInjector(injector1, injector2); + } + + public static HttpExtractor chain(HttpExtractor extractor1, HttpExtractor extractor2) { + return new ChainedHttpExtractor(extractor1, extractor2); + } + + private ChainedPropagators() {} + + static final class ChainedHttpInjector implements HttpInjector { + private final HttpInjector injector1; + private final HttpInjector injector2; + + ChainedHttpInjector(HttpInjector injector1, HttpInjector injector2) { + this.injector1 = injector1; + this.injector2 = injector2; + } + + @Override + public void inject(Context ctx, C carrier, Setter setter) { + injector1.inject(ctx, carrier, setter); + injector2.inject(ctx, carrier, setter); + } + } + + static final class ChainedHttpExtractor implements HttpExtractor { + private final HttpExtractor extractor1; + private final HttpExtractor extractor2; + + ChainedHttpExtractor(HttpExtractor extractor1, HttpExtractor extractor2) { + this.extractor1 = extractor1; + this.extractor2 = extractor2; + } + + @Override + public Context extract(Context ctx, C carrier, Getter getter) { + ctx = extractor1.extract(ctx, carrier, getter); + ctx = extractor2.extract(ctx, carrier, getter); + return ctx; + } + } +} diff --git a/api/src/main/java/io/opentelemetry/context/propagation/DefaultHttpExtractor.java b/api/src/main/java/io/opentelemetry/context/propagation/DefaultHttpExtractor.java new file mode 100644 index 00000000000..7eeba7d10af --- /dev/null +++ b/api/src/main/java/io/opentelemetry/context/propagation/DefaultHttpExtractor.java @@ -0,0 +1,35 @@ +/* + * 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.opentelemetry.context.Context; +import javax.annotation.Nullable; + +public final class DefaultHttpExtractor implements HttpExtractor { + @Override + public Context extract(Context ctx, C carrier, Getter getter) { + return ctx; + } + + static final class DefaultGetter implements Getter { + @Nullable + @Override + public String get(C carrier, String key) { + return null; + } + } +} diff --git a/api/src/main/java/io/opentelemetry/context/propagation/DefaultHttpInjector.java b/api/src/main/java/io/opentelemetry/context/propagation/DefaultHttpInjector.java new file mode 100644 index 00000000000..723087864c9 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/context/propagation/DefaultHttpInjector.java @@ -0,0 +1,29 @@ +/* + * 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.opentelemetry.context.Context; + +public final class DefaultHttpInjector implements HttpInjector { + @Override + public void inject(Context ctx, C carrier, Setter setter) {} + + static final class DefaultSetter implements Setter { + @Override + public void put(C carrier, String key, String value) {} + } +} diff --git a/api/src/main/java/io/opentelemetry/context/propagation/HttpExtractor.java b/api/src/main/java/io/opentelemetry/context/propagation/HttpExtractor.java new file mode 100644 index 00000000000..5561683d661 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/context/propagation/HttpExtractor.java @@ -0,0 +1,29 @@ +/* + * 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.opentelemetry.context.Context; +import javax.annotation.Nullable; + +public interface HttpExtractor { + Context extract(Context ctx, C carrier, Getter getter); + + interface Getter { + @Nullable + String get(C carrier, String key); + } +} diff --git a/api/src/main/java/io/opentelemetry/context/propagation/HttpInjector.java b/api/src/main/java/io/opentelemetry/context/propagation/HttpInjector.java new file mode 100644 index 00000000000..66ef815a5ff --- /dev/null +++ b/api/src/main/java/io/opentelemetry/context/propagation/HttpInjector.java @@ -0,0 +1,27 @@ +/* + * 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.opentelemetry.context.Context; + +public interface HttpInjector { + void inject(Context ctx, C carrier, Setter setter); + + interface Setter { + void put(C carrier, String key, String value); + } +} diff --git a/api/src/main/java/io/opentelemetry/context/propagation/Propagators.java b/api/src/main/java/io/opentelemetry/context/propagation/Propagators.java new file mode 100644 index 00000000000..2b76983e115 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/context/propagation/Propagators.java @@ -0,0 +1,39 @@ +/* + * 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; + +public final class Propagators { + private final HttpInjector injector; + private final HttpExtractor extractor; + + public static Propagators create(HttpInjector injector, HttpExtractor extractor) { + return new Propagators(injector, extractor); + } + + private Propagators(HttpInjector injector, HttpExtractor extractor) { + this.injector = injector; + this.extractor = extractor; + } + + public HttpExtractor getHttpExtractor() { + return extractor; + } + + public HttpInjector getHttpInjector() { + return injector; + } +} diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/DistributedContext.java b/api/src/main/java/io/opentelemetry/distributedcontext/CorrelationContext.java similarity index 74% rename from api/src/main/java/io/opentelemetry/distributedcontext/DistributedContext.java rename to api/src/main/java/io/opentelemetry/distributedcontext/CorrelationContext.java index f07ac1e950c..283171b740a 100644 --- a/api/src/main/java/io/opentelemetry/distributedcontext/DistributedContext.java +++ b/api/src/main/java/io/opentelemetry/distributedcontext/CorrelationContext.java @@ -21,7 +21,7 @@ import javax.annotation.concurrent.Immutable; /** - * A map from {@link EntryKey} to {@link EntryValue} and {@link EntryMetadata} that can be used to + * A map from {@link LabelKey} to {@link LabelValue} and {@link LabelMetadata} that can be used to * label anything that is associated with a specific operation. * *

For example, {@code DistributedContext}s can be used to label stats, log messages, or @@ -30,7 +30,7 @@ * @since 0.1.0 */ @Immutable -public interface DistributedContext { +public interface CorrelationContext { /** * Returns an immutable collection of the entries in this {@code DistributedContext}. Order of * entries is not guaranteed. @@ -38,7 +38,7 @@ public interface DistributedContext { * @return an immutable collection of the entries in this {@code DistributedContext}. * @since 0.1.0 */ - Collection getEntries(); + Collection

This must be used to create a {@link DistributedContext} when manual Context + *

This must be used to create a {@link CorrelationContext} when manual Context * propagation is used. * *

If called multiple times, only the last specified value will be used. * - * @param parent the {@link DistributedContext} used as parent, not null. + * @param parent the {@link CorrelationContext} used as parent, not null. * @return this. * @throws NullPointerException if {@code parent} is {@code null}. * @see #setNoParent() * @since 0.1.0 */ - Builder setParent(DistributedContext parent); + Builder setParent(CorrelationContext parent); /** - * Sets the option to become a root {@link DistributedContext} with no parent. If not - * called, the value provided using {@link #setParent(DistributedContext)} or otherwise {@link - * DistributedContextManager#getCurrentContext()} at {@link #build()} time will be used as + * Sets the option to become a root {@link CorrelationContext} with no parent. If not + * called, the value provided using {@link #setParent(CorrelationContext)} or otherwise {@link + * CorrelationContextManager#getCurrentContext()} at {@link #build()} time will be used as * parent. * * @return this. @@ -90,11 +90,11 @@ interface Builder { * * @param key the {@code EntryKey} which will be set. * @param value the {@code EntryValue} to set for the given key. - * @param entryMetadata the {@code EntryMetadata} associated with this {@link Entry}. + * @param entryMetadata the {@code EntryMetadata} associated with this {@link Label}. * @return this * @since 0.1.0 */ - Builder put(EntryKey key, EntryValue value, EntryMetadata entryMetadata); + Builder put(LabelKey key, LabelValue value, LabelMetadata entryMetadata); /** * Removes the key if it exists. @@ -103,7 +103,7 @@ interface Builder { * @return this * @since 0.1.0 */ - Builder remove(EntryKey key); + Builder remove(LabelKey key); /** * Creates a {@code DistributedContext} from this builder. @@ -111,6 +111,6 @@ interface Builder { * @return a {@code DistributedContext} with the same entries as this builder. * @since 0.1.0 */ - DistributedContext build(); + CorrelationContext build(); } } diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/DistributedContextManager.java b/api/src/main/java/io/opentelemetry/distributedcontext/CorrelationContextManager.java similarity index 89% rename from api/src/main/java/io/opentelemetry/distributedcontext/DistributedContextManager.java rename to api/src/main/java/io/opentelemetry/distributedcontext/CorrelationContextManager.java index cab86b3700f..188e15b0e04 100644 --- a/api/src/main/java/io/opentelemetry/distributedcontext/DistributedContextManager.java +++ b/api/src/main/java/io/opentelemetry/distributedcontext/CorrelationContextManager.java @@ -22,20 +22,20 @@ import javax.annotation.concurrent.ThreadSafe; /** - * Object for creating new {@link DistributedContext}s and {@code DistributedContext}s based on the + * Object for creating new {@link CorrelationContext}s and {@code DistributedContext}s based on the * current context. * - *

This class returns {@link DistributedContext.Builder builders} that can be used to create the - * implementation-dependent {@link DistributedContext}s. + *

This class returns {@link CorrelationContext.Builder builders} that can be used to create the + * implementation-dependent {@link CorrelationContext}s. * *

Implementations may have different constraints and are free to convert entry contexts to their * own subtypes. This means callers cannot assume the {@link #getCurrentContext() current context} - * is the same instance as the one {@link #withContext(DistributedContext) placed into scope}. + * is the same instance as the one {@link #withContext(CorrelationContext) placed into scope}. * * @since 0.1.0 */ @ThreadSafe -public interface DistributedContextManager { +public interface CorrelationContextManager { /** * Returns the current {@code DistributedContext}. @@ -43,7 +43,7 @@ public interface DistributedContextManager { * @return the current {@code DistributedContext}. * @since 0.1.0 */ - DistributedContext getCurrentContext(); + CorrelationContext getCurrentContext(); /** * Returns a new {@code Builder}. @@ -51,7 +51,7 @@ public interface DistributedContextManager { * @return a new {@code Builder}. * @since 0.1.0 */ - DistributedContext.Builder contextBuilder(); + CorrelationContext.Builder contextBuilder(); /** * Enters the scope of code where the given {@code DistributedContext} is in the current context @@ -63,7 +63,7 @@ public interface DistributedContextManager { * current context. * @since 0.1.0 */ - Scope withContext(DistributedContext distContext); + Scope withContext(CorrelationContext distContext); /** * Returns the {@link BinaryFormat} for this implementation. @@ -102,7 +102,7 @@ public interface DistributedContextManager { * @return the {@code BinaryFormat} for this implementation. * @since 0.1.0 */ - BinaryFormat getBinaryFormat(); + BinaryFormat getBinaryFormat(); /** * Returns the {@link HttpTextFormat} for this implementation. @@ -151,5 +151,5 @@ public interface DistributedContextManager { * @return the {@code HttpTextFormat} for this implementation. * @since 0.1.0 */ - HttpTextFormat getHttpTextFormat(); + HttpTextFormat getHttpTextFormat(); } diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/CorrelationsManager.java b/api/src/main/java/io/opentelemetry/distributedcontext/CorrelationsManager.java new file mode 100644 index 00000000000..cb8b67d01b5 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/distributedcontext/CorrelationsManager.java @@ -0,0 +1,43 @@ +/* + * 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.distributedcontext; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.HttpExtractor; +import io.opentelemetry.context.propagation.HttpInjector; +import java.util.List; + +public interface CorrelationsManager { + public Context setValue(Context ctx, CorrelationLabel label, HopLimit hopLimit); + + public Context setValues(Context ctx, List labels, HopLimit hopLimit); + + public interface CorrelationLabel { + public String key(); + + public String value(); + } + + public enum HopLimit { + NO_PROPAGATION, + UNLIMITED_PROPAGATION + } + + public HttpInjector getHttpInjector(); + + public HttpExtractor getHttpExtractor(); +} diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/DefaultDistributedContextManager.java b/api/src/main/java/io/opentelemetry/distributedcontext/DefaultCorrelationContextManager.java similarity index 64% rename from api/src/main/java/io/opentelemetry/distributedcontext/DefaultDistributedContextManager.java rename to api/src/main/java/io/opentelemetry/distributedcontext/DefaultCorrelationContextManager.java index 5ee832e40ea..34f6524d117 100644 --- a/api/src/main/java/io/opentelemetry/distributedcontext/DefaultDistributedContextManager.java +++ b/api/src/main/java/io/opentelemetry/distributedcontext/DefaultCorrelationContextManager.java @@ -27,71 +27,71 @@ import javax.annotation.concurrent.ThreadSafe; /** - * No-op implementations of {@link DistributedContextManager}. + * No-op implementations of {@link CorrelationContextManager}. * * @since 0.1.0 */ @ThreadSafe -public final class DefaultDistributedContextManager implements DistributedContextManager { - private static final DefaultDistributedContextManager INSTANCE = - new DefaultDistributedContextManager(); - private static final BinaryFormat BINARY_FORMAT = new NoopBinaryFormat(); - private static final HttpTextFormat HTTP_TEXT_FORMAT = +public final class DefaultCorrelationContextManager implements CorrelationContextManager { + private static final DefaultCorrelationContextManager INSTANCE = + new DefaultCorrelationContextManager(); + private static final BinaryFormat BINARY_FORMAT = new NoopBinaryFormat(); + private static final HttpTextFormat HTTP_TEXT_FORMAT = new NoopHttpTextFormat(); /** * Returns a {@code DistributedContextManager} singleton that is the default implementation for - * {@link DistributedContextManager}. + * {@link CorrelationContextManager}. * * @return a {@code DistributedContextManager} singleton that is the default implementation for - * {@link DistributedContextManager}. + * {@link CorrelationContextManager}. * @since 0.1.0 */ - public static DistributedContextManager getInstance() { + public static CorrelationContextManager getInstance() { return INSTANCE; } @Override - public DistributedContext getCurrentContext() { + public CorrelationContext getCurrentContext() { return ContextUtils.getValue(); } @Override - public DistributedContext.Builder contextBuilder() { + public CorrelationContext.Builder contextBuilder() { return new NoopDistributedContextBuilder(); } @Override - public Scope withContext(DistributedContext distContext) { + public Scope withContext(CorrelationContext distContext) { return ContextUtils.withDistributedContext(distContext); } @Override - public BinaryFormat getBinaryFormat() { + public BinaryFormat getBinaryFormat() { return BINARY_FORMAT; } @Override - public HttpTextFormat getHttpTextFormat() { + public HttpTextFormat getHttpTextFormat() { return HTTP_TEXT_FORMAT; } @Immutable - private static final class NoopDistributedContextBuilder implements DistributedContext.Builder { + private static final class NoopDistributedContextBuilder implements CorrelationContext.Builder { @Override - public DistributedContext.Builder setParent(DistributedContext parent) { + public CorrelationContext.Builder setParent(CorrelationContext parent) { Utils.checkNotNull(parent, "parent"); return this; } @Override - public DistributedContext.Builder setNoParent() { + public CorrelationContext.Builder setNoParent() { return this; } @Override - public DistributedContext.Builder put( - EntryKey key, EntryValue value, EntryMetadata tagMetadata) { + public CorrelationContext.Builder put( + LabelKey key, LabelValue value, LabelMetadata tagMetadata) { Utils.checkNotNull(key, "key"); Utils.checkNotNull(value, "value"); Utils.checkNotNull(tagMetadata, "tagMetadata"); @@ -99,53 +99,53 @@ public DistributedContext.Builder put( } @Override - public DistributedContext.Builder remove(EntryKey key) { + public CorrelationContext.Builder remove(LabelKey key) { Utils.checkNotNull(key, "key"); return this; } @Override - public DistributedContext build() { - return EmptyDistributedContext.getInstance(); + public CorrelationContext build() { + return EmptyCorrelationContext.getInstance(); } } @Immutable - private static final class NoopBinaryFormat implements BinaryFormat { + private static final class NoopBinaryFormat implements BinaryFormat { static final byte[] EMPTY_BYTE_ARRAY = {}; @Override - public byte[] toByteArray(DistributedContext distContext) { + public byte[] toByteArray(CorrelationContext distContext) { Utils.checkNotNull(distContext, "distContext"); return EMPTY_BYTE_ARRAY; } @Override - public DistributedContext fromByteArray(byte[] bytes) { + public CorrelationContext fromByteArray(byte[] bytes) { Utils.checkNotNull(bytes, "bytes"); - return EmptyDistributedContext.getInstance(); + return EmptyCorrelationContext.getInstance(); } } @Immutable - private static final class NoopHttpTextFormat implements HttpTextFormat { + private static final class NoopHttpTextFormat implements HttpTextFormat { @Override public List fields() { return Collections.emptyList(); } @Override - public void inject(DistributedContext distContext, C carrier, Setter setter) { + public void inject(CorrelationContext distContext, C carrier, Setter setter) { Utils.checkNotNull(distContext, "distContext"); Utils.checkNotNull(carrier, "carrier"); Utils.checkNotNull(setter, "setter"); } @Override - public DistributedContext extract(C carrier, Getter getter) { + public CorrelationContext extract(C carrier, Getter getter) { Utils.checkNotNull(carrier, "carrier"); Utils.checkNotNull(getter, "getter"); - return EmptyDistributedContext.getInstance(); + return EmptyCorrelationContext.getInstance(); } } } diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/EmptyDistributedContext.java b/api/src/main/java/io/opentelemetry/distributedcontext/EmptyCorrelationContext.java similarity index 68% rename from api/src/main/java/io/opentelemetry/distributedcontext/EmptyDistributedContext.java rename to api/src/main/java/io/opentelemetry/distributedcontext/EmptyCorrelationContext.java index 46bef8ea369..9294ef29a26 100644 --- a/api/src/main/java/io/opentelemetry/distributedcontext/EmptyDistributedContext.java +++ b/api/src/main/java/io/opentelemetry/distributedcontext/EmptyCorrelationContext.java @@ -22,34 +22,34 @@ import javax.annotation.concurrent.Immutable; /** - * An immutable implementation of the {@link DistributedContext} that does not contain any entries. + * An immutable implementation of the {@link CorrelationContext} that does not contain any entries. */ @Immutable -public class EmptyDistributedContext implements DistributedContext { - private static final Collection EMPTY_COLLECTION = Collections.emptyList(); +public class EmptyCorrelationContext implements CorrelationContext { + private static final Collection

Each {@code EntryKey} has a {@code String} name. Names have a maximum length of {@link * #MAX_LENGTH} and contain only printable ASCII characters. @@ -34,7 +34,7 @@ */ @Immutable @AutoValue -public abstract class EntryKey { +public abstract class LabelKey { /** * The maximum length for an entry key name. The value is {@value #MAX_LENGTH}. * @@ -42,7 +42,7 @@ public abstract class EntryKey { */ public static final int MAX_LENGTH = 255; - EntryKey() {} + LabelKey() {} /** * Constructs an {@code EntryKey} with the given name. @@ -59,9 +59,9 @@ public abstract class EntryKey { * @throws IllegalArgumentException if the name is not valid. * @since 0.1.0 */ - public static EntryKey create(String name) { + public static LabelKey create(String name) { Utils.checkArgument(isValid(name), "Invalid EntryKey name: %s", name); - return new AutoValue_EntryKey(name); + return new AutoValue_LabelKey(name); } /** diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/EntryMetadata.java b/api/src/main/java/io/opentelemetry/distributedcontext/LabelMetadata.java similarity index 71% rename from api/src/main/java/io/opentelemetry/distributedcontext/EntryMetadata.java rename to api/src/main/java/io/opentelemetry/distributedcontext/LabelMetadata.java index ce90a76d9f3..b4dc740e7a1 100644 --- a/api/src/main/java/io/opentelemetry/distributedcontext/EntryMetadata.java +++ b/api/src/main/java/io/opentelemetry/distributedcontext/LabelMetadata.java @@ -20,40 +20,40 @@ import javax.annotation.concurrent.Immutable; /** - * {@link EntryMetadata} contains properties associated with an {@link Entry}. + * {@link LabelMetadata} contains properties associated with an {@link Label}. * - *

For now only the property {@link EntryTtl} is defined. In future, additional properties may be + *

For now only the property {@link HopLimit} is defined. In future, additional properties may be * added to address specific situations. * * @since 0.1.0 */ @Immutable @AutoValue -public abstract class EntryMetadata { +public abstract class LabelMetadata { - EntryMetadata() {} + LabelMetadata() {} /** - * Creates an {@link EntryMetadata} with the given {@link EntryTtl}. + * Creates an {@link LabelMetadata} with the given {@link HopLimit}. * * @param entryTtl TTL of an {@code Entry}. * @return an {@code EntryMetadata}. * @since 0.1.0 */ - public static EntryMetadata create(EntryTtl entryTtl) { - return new AutoValue_EntryMetadata(entryTtl); + public static LabelMetadata create(HopLimit entryTtl) { + return new AutoValue_LabelMetadata(entryTtl); } /** - * Returns the {@link EntryTtl} of this {@link EntryMetadata}. + * Returns the {@link HopLimit} of this {@link LabelMetadata}. * * @return the {@code EntryTtl}. * @since 0.1.0 */ - public abstract EntryTtl getEntryTtl(); + public abstract HopLimit getEntryTtl(); /** - * {@link EntryTtl} is an integer that represents number of hops an entry can propagate. + * {@link HopLimit} is an integer that represents number of hops an entry can propagate. * *

Anytime a sender serializes a entry, sends it over the wire and receiver deserializes the * entry then the entry is considered to have travelled one hop. @@ -61,11 +61,11 @@ public static EntryMetadata create(EntryTtl entryTtl) { *

There could be one or more proxy(ies) between sender and receiver. Proxies are treated as * transparent entities and they are not counted as hops. * - *

For now, only special values of {@link EntryTtl} are supported. + *

For now, only special values of {@link HopLimit} are supported. * * @since 0.1.0 */ - public enum EntryTtl { + public enum HopLimit { /** * An {@link Entry} with {@link EntryTtl#NO_PROPAGATION} is considered to have local scope and @@ -73,7 +73,7 @@ public enum EntryTtl { * * @since 0.1.0 */ - NO_PROPAGATION(0), + NO_PROPAGATION, /** * An {@link Entry} with {@link EntryTtl#UNLIMITED_PROPAGATION} can propagate unlimited hops. @@ -85,16 +85,6 @@ public enum EntryTtl { * * @since 0.1.0 */ - UNLIMITED_PROPAGATION(-1); - - private final int hops; - - EntryTtl(int hops) { - this.hops = hops; - } - - int getHops() { - return hops; - } + UNLIMITED_PROPAGATION; } } diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/EntryValue.java b/api/src/main/java/io/opentelemetry/distributedcontext/LabelValue.java similarity index 93% rename from api/src/main/java/io/opentelemetry/distributedcontext/EntryValue.java rename to api/src/main/java/io/opentelemetry/distributedcontext/LabelValue.java index 757ce379142..ec60d92f88e 100644 --- a/api/src/main/java/io/opentelemetry/distributedcontext/EntryValue.java +++ b/api/src/main/java/io/opentelemetry/distributedcontext/LabelValue.java @@ -31,7 +31,7 @@ */ @Immutable @AutoValue -public abstract class EntryValue { +public abstract class LabelValue { /** * The maximum length for a entry value. The value is {@value #MAX_LENGTH}. * @@ -39,7 +39,7 @@ public abstract class EntryValue { */ public static final int MAX_LENGTH = 255; - EntryValue() {} + LabelValue() {} /** * Constructs an {@code EntryValue} from the given string. The string must meet the following @@ -55,9 +55,9 @@ public abstract class EntryValue { * @throws IllegalArgumentException if the {@code String} is not valid. * @since 0.1.0 */ - public static EntryValue create(String value) { + public static LabelValue create(String value) { Utils.checkArgument(isValid(value), "Invalid EntryValue: %s", value); - return new AutoValue_EntryValue(value); + return new AutoValue_LabelValue(value); } /** diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/package-info.java b/api/src/main/java/io/opentelemetry/distributedcontext/package-info.java index f842efa2eca..a991199fa4a 100644 --- a/api/src/main/java/io/opentelemetry/distributedcontext/package-info.java +++ b/api/src/main/java/io/opentelemetry/distributedcontext/package-info.java @@ -21,10 +21,10 @@ * to label anything that is associated with a specific operation. For example, the {@code * opentelemetry.stats} package labels all stats with the current entries. * - *

{@link io.opentelemetry.distributedcontext.Entry Entrys} are key-value pairs. The {@link - * io.opentelemetry.distributedcontext.EntryKey keys} and {@link - * io.opentelemetry.distributedcontext.EntryValue values} are wrapped {@code String}s. They are - * stored as a map in a {@link io.opentelemetry.distributedcontext.DistributedContext}. + *

{@link io.opentelemetry.distributedcontext.Label Entrys} are key-value pairs. The {@link + * io.opentelemetry.distributedcontext.LabelKey keys} and {@link + * io.opentelemetry.distributedcontext.LabelValue values} are wrapped {@code String}s. They are + * stored as a map in a {@link io.opentelemetry.distributedcontext.CorrelationContext}. * *

Note that entries are independent of the tracing data that is propagated in the {@code * io.grpc.Context}, such as trace ID. diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/propagation/ContextKeys.java b/api/src/main/java/io/opentelemetry/distributedcontext/propagation/ContextKeys.java new file mode 100644 index 00000000000..34642ed31a8 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/distributedcontext/propagation/ContextKeys.java @@ -0,0 +1,31 @@ +/* + * 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.distributedcontext.propagation; + +import io.opentelemetry.context.Context; +import io.opentelemetry.distributedcontext.CorrelationContext; + +public final class ContextKeys { + private static final Context.Key CORRELATION_CONTEXT_KEY = + Context.createKey("correlation-context"); + + public static Context.Key getSpanContextKey() { + return CORRELATION_CONTEXT_KEY; + } + + private ContextKeys() {} +} diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/propagation/DefaultCorrelationContextExtractor.java b/api/src/main/java/io/opentelemetry/distributedcontext/propagation/DefaultCorrelationContextExtractor.java new file mode 100644 index 00000000000..538cdb507ae --- /dev/null +++ b/api/src/main/java/io/opentelemetry/distributedcontext/propagation/DefaultCorrelationContextExtractor.java @@ -0,0 +1,28 @@ +/* + * 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.distributedcontext.propagation; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.HttpExtractor; + +public final class DefaultCorrelationContextExtractor implements HttpExtractor { + @Override + public Context extract(Context ctx, C carrier, Getter getter) { + // TODO - Implement (outside the bounds of this prototype). + return ctx; + } +} diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/propagation/DefaultCorrelationContextInjector.java b/api/src/main/java/io/opentelemetry/distributedcontext/propagation/DefaultCorrelationContextInjector.java new file mode 100644 index 00000000000..40cf66746a2 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/distributedcontext/propagation/DefaultCorrelationContextInjector.java @@ -0,0 +1,27 @@ +/* + * 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.distributedcontext.propagation; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.HttpInjector; + +public final class DefaultCorrelationContextInjector implements HttpInjector { + @Override + public void inject(Context ctx, C carrier, Setter getter) { + // TODO - Implement (outside the bounds of this prototype). + } +} diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/spi/DistributedContextManagerProvider.java b/api/src/main/java/io/opentelemetry/distributedcontext/spi/CorrelationContextManagerProvider.java similarity index 88% rename from api/src/main/java/io/opentelemetry/distributedcontext/spi/DistributedContextManagerProvider.java rename to api/src/main/java/io/opentelemetry/distributedcontext/spi/CorrelationContextManagerProvider.java index 637ece87035..73238fcf3d1 100644 --- a/api/src/main/java/io/opentelemetry/distributedcontext/spi/DistributedContextManagerProvider.java +++ b/api/src/main/java/io/opentelemetry/distributedcontext/spi/CorrelationContextManagerProvider.java @@ -16,11 +16,11 @@ package io.opentelemetry.distributedcontext.spi; -import io.opentelemetry.distributedcontext.DistributedContextManager; +import io.opentelemetry.distributedcontext.CorrelationContextManager; import javax.annotation.concurrent.ThreadSafe; /** - * DistributedContextManagerProvider is a service provider for {@link DistributedContextManager}. + * DistributedContextManagerProvider is a service provider for {@link CorrelationContextManager}. * Fully qualified class name of the implementation should be registered in {@code * META-INF/services/io.opentelemetry.distributedcontext.spi.DistributedContextManagerProvider}. *
@@ -32,7 +32,7 @@ * @see io.opentelemetry.OpenTelemetry */ @ThreadSafe -public interface DistributedContextManagerProvider { +public interface CorrelationContextManagerProvider { /** * Creates a new {@code DistributedContextManager} instance. @@ -40,5 +40,5 @@ public interface DistributedContextManagerProvider { * @return a {@code DistributedContextManager} instance. * @since 0.1.0 */ - DistributedContextManager create(); + CorrelationContextManager create(); } diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/unsafe/ContextUtils.java b/api/src/main/java/io/opentelemetry/distributedcontext/unsafe/ContextUtils.java index 209378aa8d3..5bd93b387a0 100644 --- a/api/src/main/java/io/opentelemetry/distributedcontext/unsafe/ContextUtils.java +++ b/api/src/main/java/io/opentelemetry/distributedcontext/unsafe/ContextUtils.java @@ -18,24 +18,24 @@ import io.grpc.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.distributedcontext.DistributedContext; -import io.opentelemetry.distributedcontext.EmptyDistributedContext; +import io.opentelemetry.distributedcontext.CorrelationContext; +import io.opentelemetry.distributedcontext.EmptyCorrelationContext; import javax.annotation.concurrent.Immutable; /** - * Utility methods for accessing the {@link DistributedContext} contained in the {@link + * Utility methods for accessing the {@link CorrelationContext} contained in the {@link * io.grpc.Context}. * *

Most code should interact with the current context via the public APIs in {@link - * DistributedContext} and avoid accessing this class directly. + * CorrelationContext} and avoid accessing this class directly. * * @since 0.1.0 */ @Immutable public final class ContextUtils { - private static final Context.Key DIST_CONTEXT_KEY = + private static final Context.Key DIST_CONTEXT_KEY = Context.keyWithDefault( - "opentelemetry-dist-context-key", EmptyDistributedContext.getInstance()); + "opentelemetry-dist-context-key", EmptyCorrelationContext.getInstance()); /** * Creates a new {@code Context} with the given value set. @@ -44,7 +44,7 @@ public final class ContextUtils { * @return a new context with the given value set. * @since 0.1.0 */ - public static Context withValue(DistributedContext distContext) { + public static Context withValue(CorrelationContext distContext) { return Context.current().withValue(DIST_CONTEXT_KEY, distContext); } @@ -56,7 +56,7 @@ public static Context withValue(DistributedContext distContext) { * @return a new context with the given value set. * @since 0.1.0 */ - public static Context withValue(DistributedContext distContext, Context context) { + public static Context withValue(CorrelationContext distContext, Context context) { return context.withValue(DIST_CONTEXT_KEY, distContext); } @@ -66,7 +66,7 @@ public static Context withValue(DistributedContext distContext, Context context) * @return the value from the specified {@code Context}. * @since 0.1.0 */ - public static DistributedContext getValue() { + public static CorrelationContext getValue() { return DIST_CONTEXT_KEY.get(); } @@ -77,7 +77,7 @@ public static DistributedContext getValue() { * @return the value from the specified {@code Context}. * @since 0.1.0 */ - public static DistributedContext getValue(Context context) { + public static CorrelationContext getValue(Context context) { return DIST_CONTEXT_KEY.get(context); } @@ -89,7 +89,7 @@ public static DistributedContext getValue(Context context) { * @return the {@link Scope} for the updated {@code Context}. * @since 0.1.0 */ - public static Scope withDistributedContext(DistributedContext distContext) { + public static Scope withDistributedContext(CorrelationContext distContext) { return DistributedContextInScope.create(distContext); } diff --git a/api/src/main/java/io/opentelemetry/distributedcontext/unsafe/DistributedContextInScope.java b/api/src/main/java/io/opentelemetry/distributedcontext/unsafe/DistributedContextInScope.java index a386ae1b8e7..cf4ba65b29f 100644 --- a/api/src/main/java/io/opentelemetry/distributedcontext/unsafe/DistributedContextInScope.java +++ b/api/src/main/java/io/opentelemetry/distributedcontext/unsafe/DistributedContextInScope.java @@ -18,17 +18,17 @@ import io.grpc.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.distributedcontext.DistributedContext; +import io.opentelemetry.distributedcontext.CorrelationContext; /** - * A scope that manages the {@link Context} for a {@link DistributedContext}. + * A scope that manages the {@link Context} for a {@link CorrelationContext}. * * @since 0.1.0 */ final class DistributedContextInScope implements Scope { private final Context orig; - private DistributedContextInScope(DistributedContext distContext) { + private DistributedContextInScope(CorrelationContext distContext) { orig = ContextUtils.withValue(distContext).attach(); } @@ -38,7 +38,7 @@ private DistributedContextInScope(DistributedContext distContext) { * @param distContext the {@code DistributedContext} to be added to the current {@code Context}. * @since 0.1.0 */ - static DistributedContextInScope create(DistributedContext distContext) { + static DistributedContextInScope create(CorrelationContext distContext) { return new DistributedContextInScope(distContext); } diff --git a/api/src/main/java/io/opentelemetry/trace/propagation/ContextKeys.java b/api/src/main/java/io/opentelemetry/trace/propagation/ContextKeys.java new file mode 100644 index 00000000000..f3ca4832f19 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/trace/propagation/ContextKeys.java @@ -0,0 +1,31 @@ +/* + * 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.trace.propagation; + +import io.opentelemetry.context.Context; +import io.opentelemetry.trace.SpanContext; + +public final class ContextKeys { + private static final Context.Key SPAN_CONTEXT_KEY = + Context.createKey("span-context"); + + public static Context.Key getSpanContextKey() { + return SPAN_CONTEXT_KEY; + } + + private ContextKeys() {} +} diff --git a/api/src/main/java/io/opentelemetry/trace/propagation/HttpTraceContextExtractor.java b/api/src/main/java/io/opentelemetry/trace/propagation/HttpTraceContextExtractor.java new file mode 100644 index 00000000000..20953cbe1b6 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/trace/propagation/HttpTraceContextExtractor.java @@ -0,0 +1,48 @@ +/* + * 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.trace.propagation; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.HttpExtractor; +import io.opentelemetry.context.propagation.HttpTextFormat; +import io.opentelemetry.trace.SpanContext; +import javax.annotation.Nullable; + +public final class HttpTraceContextExtractor implements HttpExtractor { + private static final HttpTraceContext PROPAGATOR = new HttpTraceContext(); + + @Override + public Context extract(Context ctx, C carrier, Getter getter) { + SpanContext spanCtx = PROPAGATOR.extract(carrier, new GetterImpl(getter)); + return ctx.setValue(ContextKeys.getSpanContextKey(), spanCtx); + } + + // Utility class, not relevant. + static final class GetterImpl implements HttpTextFormat.Getter { + Getter wrapped; + + GetterImpl(Getter wrapped) { + this.wrapped = wrapped; + } + + @Nullable + @Override + public String get(C carrier, String key) { + return wrapped.get(carrier, key); + } + } +} diff --git a/api/src/main/java/io/opentelemetry/trace/propagation/HttpTraceContextInjector.java b/api/src/main/java/io/opentelemetry/trace/propagation/HttpTraceContextInjector.java new file mode 100644 index 00000000000..dfadbc07425 --- /dev/null +++ b/api/src/main/java/io/opentelemetry/trace/propagation/HttpTraceContextInjector.java @@ -0,0 +1,50 @@ +/* + * 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.trace.propagation; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.HttpInjector; +import io.opentelemetry.context.propagation.HttpTextFormat; +import io.opentelemetry.trace.SpanContext; + +public final class HttpTraceContextInjector implements HttpInjector { + private static final HttpTraceContext PROPAGATOR = new HttpTraceContext(); + + @Override + public void inject(Context ctx, C carrier, Setter setter) { + SpanContext spanCtx = ctx.getValue(ContextKeys.getSpanContextKey()); + if (spanCtx == null) { + return; + } + + PROPAGATOR.inject(spanCtx, carrier, new SetterImpl(setter)); + } + + // Utility class, not relevant. + static final class SetterImpl implements HttpTextFormat.Setter { + Setter wrapped; + + SetterImpl(Setter wrapped) { + this.wrapped = wrapped; + } + + @Override + public void put(C carrier, String key, String value) { + wrapped.put(carrier, key, value); + } + } +} diff --git a/api/src/test/java/io/opentelemetry/OpenTelemetryTest.java b/api/src/test/java/io/opentelemetry/OpenTelemetryTest.java index 7c64e7c3700..2ffc4875ef5 100644 --- a/api/src/test/java/io/opentelemetry/OpenTelemetryTest.java +++ b/api/src/test/java/io/opentelemetry/OpenTelemetryTest.java @@ -22,10 +22,10 @@ import io.opentelemetry.context.Scope; import io.opentelemetry.context.propagation.BinaryFormat; import io.opentelemetry.context.propagation.HttpTextFormat; -import io.opentelemetry.distributedcontext.DefaultDistributedContextManager; -import io.opentelemetry.distributedcontext.DistributedContext; -import io.opentelemetry.distributedcontext.DistributedContextManager; -import io.opentelemetry.distributedcontext.spi.DistributedContextManagerProvider; +import io.opentelemetry.distributedcontext.CorrelationContext; +import io.opentelemetry.distributedcontext.CorrelationContextManager; +import io.opentelemetry.distributedcontext.DefaultCorrelationContextManager; +import io.opentelemetry.distributedcontext.spi.CorrelationContextManagerProvider; import io.opentelemetry.metrics.CounterDouble; import io.opentelemetry.metrics.CounterLong; import io.opentelemetry.metrics.DefaultMeter; @@ -73,7 +73,7 @@ public void after() { OpenTelemetry.reset(); System.clearProperty(TracerFactoryProvider.class.getName()); System.clearProperty(MeterProvider.class.getName()); - System.clearProperty(DistributedContextManagerProvider.class.getName()); + System.clearProperty(CorrelationContextManagerProvider.class.getName()); } @Test @@ -84,10 +84,10 @@ public void testDefault() { .isEqualTo(OpenTelemetry.getTracerFactory().get("testTracer")); assertThat(OpenTelemetry.getMeter()).isInstanceOf(DefaultMeter.getInstance().getClass()); assertThat(OpenTelemetry.getMeter()).isEqualTo(OpenTelemetry.getMeter()); - assertThat(OpenTelemetry.getDistributedContextManager()) - .isInstanceOf(DefaultDistributedContextManager.getInstance().getClass()); - assertThat(OpenTelemetry.getDistributedContextManager()) - .isEqualTo(OpenTelemetry.getDistributedContextManager()); + assertThat(OpenTelemetry.getCorrelationContextManager()) + .isInstanceOf(DefaultCorrelationContextManager.getInstance().getClass()); + assertThat(OpenTelemetry.getCorrelationContextManager()) + .isEqualTo(OpenTelemetry.getCorrelationContextManager()); } @Test @@ -160,16 +160,16 @@ public void testMeterNotFound() { public void testDistributedContextManagerLoadArbitrary() throws IOException { File serviceFile = createService( - DistributedContextManagerProvider.class, + CorrelationContextManagerProvider.class, FirstDistributedContextManager.class, SecondDistributedContextManager.class); try { assertTrue( - (OpenTelemetry.getDistributedContextManager() instanceof FirstDistributedContextManager) - || (OpenTelemetry.getDistributedContextManager() + (OpenTelemetry.getCorrelationContextManager() instanceof FirstDistributedContextManager) + || (OpenTelemetry.getCorrelationContextManager() instanceof SecondDistributedContextManager)); - assertThat(OpenTelemetry.getDistributedContextManager()) - .isEqualTo(OpenTelemetry.getDistributedContextManager()); + assertThat(OpenTelemetry.getCorrelationContextManager()) + .isEqualTo(OpenTelemetry.getCorrelationContextManager()); } finally { serviceFile.delete(); } @@ -179,17 +179,17 @@ public void testDistributedContextManagerLoadArbitrary() throws IOException { public void testDistributedContextManagerSystemProperty() throws IOException { File serviceFile = createService( - DistributedContextManagerProvider.class, + CorrelationContextManagerProvider.class, FirstDistributedContextManager.class, SecondDistributedContextManager.class); System.setProperty( - DistributedContextManagerProvider.class.getName(), + CorrelationContextManagerProvider.class.getName(), SecondDistributedContextManager.class.getName()); try { - assertThat(OpenTelemetry.getDistributedContextManager()) + assertThat(OpenTelemetry.getCorrelationContextManager()) .isInstanceOf(SecondDistributedContextManager.class); - assertThat(OpenTelemetry.getDistributedContextManager()) - .isEqualTo(OpenTelemetry.getDistributedContextManager()); + assertThat(OpenTelemetry.getCorrelationContextManager()) + .isEqualTo(OpenTelemetry.getCorrelationContextManager()); } finally { serviceFile.delete(); } @@ -197,9 +197,9 @@ public void testDistributedContextManagerSystemProperty() throws IOException { @Test public void testDistributedContextManagerNotFound() { - System.setProperty(DistributedContextManagerProvider.class.getName(), "io.does.not.exists"); + System.setProperty(CorrelationContextManagerProvider.class.getName(), "io.does.not.exists"); thrown.expect(IllegalStateException.class); - OpenTelemetry.getDistributedContextManager(); + OpenTelemetry.getCorrelationContextManager(); } private static File createService(Class service, Class... impls) throws IOException { @@ -351,45 +351,45 @@ public MeasureBatchRecorder newMeasureBatchRecorder() { public static class SecondDistributedContextManager extends FirstDistributedContextManager { @Override - public DistributedContextManager create() { + public CorrelationContextManager create() { return new SecondDistributedContextManager(); } } public static class FirstDistributedContextManager - implements DistributedContextManager, DistributedContextManagerProvider { + implements CorrelationContextManager, CorrelationContextManagerProvider { @Override - public DistributedContextManager create() { + public CorrelationContextManager create() { return new FirstDistributedContextManager(); } @Nullable @Override - public DistributedContext getCurrentContext() { + public CorrelationContext getCurrentContext() { return null; } @Nullable @Override - public DistributedContext.Builder contextBuilder() { + public CorrelationContext.Builder contextBuilder() { return null; } @Nullable @Override - public Scope withContext(DistributedContext distContext) { + public Scope withContext(CorrelationContext distContext) { return null; } @Nullable @Override - public BinaryFormat getBinaryFormat() { + public BinaryFormat getBinaryFormat() { return null; } @Nullable @Override - public HttpTextFormat getHttpTextFormat() { + public HttpTextFormat getHttpTextFormat() { return null; } } diff --git a/api/src/test/java/io/opentelemetry/contextprop/PropagatorsTest.java b/api/src/test/java/io/opentelemetry/contextprop/PropagatorsTest.java new file mode 100644 index 00000000000..480b18999dd --- /dev/null +++ b/api/src/test/java/io/opentelemetry/contextprop/PropagatorsTest.java @@ -0,0 +1,131 @@ +/* + * 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.contextprop; + +import static io.opentelemetry.trace.propagation.ContextKeys.getSpanContextKey; + +import io.opentelemetry.OpenTelemetry; +import io.opentelemetry.baggage.DefaultBaggageManager; +import io.opentelemetry.baggage.propagation.DefaultBaggageExtractor; +import io.opentelemetry.baggage.propagation.DefaultBaggageInjector; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.context.propagation.ChainedPropagators; +import io.opentelemetry.context.propagation.HttpExtractor; +import io.opentelemetry.context.propagation.HttpInjector; +import io.opentelemetry.distributedcontext.CorrelationContext; +import io.opentelemetry.distributedcontext.LabelKey; +import io.opentelemetry.distributedcontext.LabelMetadata; +import io.opentelemetry.distributedcontext.LabelValue; +import io.opentelemetry.distributedcontext.propagation.DefaultCorrelationContextExtractor; +import io.opentelemetry.distributedcontext.propagation.DefaultCorrelationContextInjector; +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.propagation.HttpTraceContextExtractor; +import io.opentelemetry.trace.propagation.HttpTraceContextInjector; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class PropagatorsTest { + @Test + public void testSimpleRequest() { + Map inboundCarrier = new HashMap<>(); + + // Chain the extractors. + HttpExtractor extractor = + ChainedPropagators.chain( + ChainedPropagators.chain( + new HttpTraceContextExtractor(), new DefaultCorrelationContextExtractor()), + new DefaultBaggageExtractor()); + + // Chain the injectors. + HttpInjector injector = + ChainedPropagators.chain( + ChainedPropagators.chain( + new HttpTraceContextInjector(), new DefaultCorrelationContextInjector()), + new DefaultBaggageInjector()); + + // Initialize by injecting an empty SpanContext. + Context initialCtx = + Context.current() + .setValue( + getSpanContextKey(), + SpanContext.create( + TraceId.getInvalid(), + SpanId.getInvalid(), + TraceFlags.getDefault(), + Tracestate.getDefault())); + injector.inject(initialCtx, inboundCarrier, new MapSetter()); + + // Extract. + Context ctx = extractor.extract(Context.current(), inboundCarrier, new MapGetter()); + + Scope scope = Context.setCurrent(ctx); + try { + // Explicit style (pass Context, use opaque object underneath). + Context newCtx = + DefaultBaggageManager.getInstance().setValue(Context.current(), "mykey", "myvalue"); + Scope bagScope = Context.setCurrent(newCtx); + try { + + // Implicit style (do not pass Context, use specific interface/object). + CorrelationContext corrCtx = + OpenTelemetry.getCorrelationContextManager() + .contextBuilder() + .setParent(OpenTelemetry.getCorrelationContextManager().getCurrentContext()) + .put( + LabelKey.create("key1"), + LabelValue.create("label1"), + LabelMetadata.create(LabelMetadata.HopLimit.UNLIMITED_PROPAGATION)) + .build(); + Scope corrScope = OpenTelemetry.getCorrelationContextManager().withContext(corrCtx); + try { + // Inject everything that is active at this point. + Map outboundCarrier = new HashMap<>(); + injector.inject(Context.current(), outboundCarrier, new MapSetter()); + } finally { + corrScope.close(); + } + } finally { + bagScope.close(); + } + } finally { + scope.close(); + } + } + + static final class MapGetter implements HttpExtractor.Getter> { + @Override + public String get(Map carrier, String key) { + return carrier.get(key); + } + } + + static final class MapSetter implements HttpInjector.Setter> { + @Override + public void put(Map carrier, String key, String value) { + carrier.put(key, value); + } + } +} diff --git a/api/src/test/java/io/opentelemetry/distributedcontext/DefaultDistributedContextManagerTest.java b/api/src/test/java/io/opentelemetry/distributedcontext/DefaultDistributedContextManagerTest.java index 93fbf190255..898b5987348 100644 --- a/api/src/test/java/io/opentelemetry/distributedcontext/DefaultDistributedContextManagerTest.java +++ b/api/src/test/java/io/opentelemetry/distributedcontext/DefaultDistributedContextManagerTest.java @@ -30,25 +30,25 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Unit tests for {@link DefaultDistributedContextManager}. */ +/** Unit tests for {@link DefaultCorrelationContextManager}. */ @RunWith(JUnit4.class) public final class DefaultDistributedContextManagerTest { - private static final DistributedContextManager defaultDistributedContextManager = - DefaultDistributedContextManager.getInstance(); - private static final EntryKey KEY = EntryKey.create("key"); - private static final EntryValue VALUE = EntryValue.create("value"); + private static final CorrelationContextManager defaultDistributedContextManager = + DefaultCorrelationContextManager.getInstance(); + private static final LabelKey KEY = LabelKey.create("key"); + private static final LabelValue VALUE = LabelValue.create("value"); - private static final DistributedContext DIST_CONTEXT = - new DistributedContext() { + private static final CorrelationContext DIST_CONTEXT = + new CorrelationContext() { @Override - public Collection getEntries() { - return Arrays.asList(Entry.create(KEY, VALUE, Entry.METADATA_UNLIMITED_PROPAGATION)); + public Collection

Filter can be programmatically added to {@link ServletContext} or initialized via web.xml. + * + *

Following code examples show possible initialization: + * + *

{@code
+ * TracingFilter filter = new TracingFilter(tracer);
+ *  servletContext.addFilter("tracingFilter", filter);
+ * }
+ * + *

Or include filter in web.xml and: + * + *

{@code
+ * GlobalTracer.register(tracer);
+ * // optional, if no present ServletFilterSpanDecorator.STANDARD_TAGS is applied
+ * servletContext.setAttribute({@link TracingFilter#SPAN_DECORATORS}, listOfDecorators);  *
+ * }
+ * + *

Current server span context is accessible via {@link HttpServletRequest#getAttribute(String)} + * with name {@link TracingFilter#SERVER_SPAN_CONTEXT}. + * + * @author Pavol Loffay + */ +public class TracingFilter implements Filter { + private static final Logger log = Logger.getLogger(TracingFilter.class.getName()); + + /** Use as a key of {@link ServletContext#setAttribute(String, Object)} to set span decorators. */ + public static final String SPAN_DECORATORS = TracingFilter.class.getName() + ".spanDecorators"; + /** Use as a key of {@link ServletContext#setAttribute(String, Object)} to skip pattern. */ + public static final String SKIP_PATTERN = TracingFilter.class.getName() + ".skipPattern"; + + /** + * Used as a key of {@link HttpServletRequest#setAttribute(String, Object)} to inject server span + * context. + */ + public static final String SERVER_SPAN_CONTEXT = + TracingFilter.class.getName() + ".activeSpanContext"; + + protected Tracer tracer; + private List spanDecorators; + private Pattern skipPattern; + + /** + * Summary. + * + * @param tracer the tracer. + */ + public TracingFilter(Tracer tracer) { + this(tracer, Collections.singletonList(ServletFilterSpanDecorator.STANDARD_TAGS), null); + } + + /** + * Summary. + * + * @param tracer tracer + * @param spanDecorators decorators + * @param skipPattern null or pattern to exclude certain paths from tracing e.g. "/health" + */ + public TracingFilter( + Tracer tracer, List spanDecorators, Pattern skipPattern) { + this.tracer = tracer; + this.spanDecorators = new ArrayList<>(spanDecorators); + this.spanDecorators.removeAll(Collections.singleton(null)); + this.skipPattern = skipPattern; + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + ServletContext servletContext = filterConfig.getServletContext(); + + // Check whether the servlet context provides a tracer + Object tracerObj = servletContext.getAttribute(Tracer.class.getName()); + if (tracerObj instanceof Tracer) { + tracer = (Tracer) tracerObj; + } else { + // Add current tracer to servlet context, so available to webapp + servletContext.setAttribute(Tracer.class.getName(), tracer); + } + + // use decorators from context attributes + Object contextAttribute = servletContext.getAttribute(SPAN_DECORATORS); + if (contextAttribute instanceof Collection) { + List decorators = new ArrayList<>(); + for (Object decorator : (Collection) contextAttribute) { + if (decorator instanceof ServletFilterSpanDecorator) { + decorators.add((ServletFilterSpanDecorator) decorator); + } else { + log.severe(decorator + " is not an instance of " + ServletFilterSpanDecorator.class); + } + } + this.spanDecorators = decorators.size() > 0 ? decorators : this.spanDecorators; + } + + contextAttribute = servletContext.getAttribute(SKIP_PATTERN); + if (contextAttribute instanceof Pattern) { + skipPattern = (Pattern) contextAttribute; + } + + // Initialize the propagators. + Propagators propagators = + Propagators.create( + new DefaultHttpInjector(), + ChainedPropagators.chain( + new HttpTraceContextExtractor(), new DefaultCorrelationContextExtractor())); + OpenTelemetry.setPropagators(propagators); + } + + @Override + public void doFilter( + ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) + throws IOException, ServletException { + + HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; + HttpServletResponse httpResponse = (HttpServletResponse) servletResponse; + + if (!isTraced(httpRequest, httpResponse)) { + chain.doFilter(httpRequest, httpResponse); + return; + } + + /** If request is traced then do not start new span. */ + if (servletRequest.getAttribute(SERVER_SPAN_CONTEXT) != null) { + chain.doFilter(servletRequest, servletResponse); + } else { + /** + * SpanContext *and* other members (such as correlationcontext) would be extracted here, and + * make it available in the returned Context object. + * + *

For further consumption, the returned Context object would need to be explicitly passed + * to DistributedContext/Baggage handlers, or else set it automatically as the current + * instance. + */ + Context ctx = + OpenTelemetry.getPropagators() + .getHttpExtractor() + .extract(Context.current(), httpRequest, HttpServletRequestGetter.getInstance()); + SpanContext extractedContext = ctx.getValue(ContextKeys.getSpanContextKey()); + + final Span span = + tracer + .spanBuilder(httpRequest.getMethod()) + .setParent(extractedContext) + .setSpanKind(Span.Kind.SERVER) + .startSpan(); + + httpRequest.setAttribute(SERVER_SPAN_CONTEXT, span.getContext()); + + for (ServletFilterSpanDecorator spanDecorator : spanDecorators) { + spanDecorator.onRequest(httpRequest, span); + } + + Scope scope = tracer.withSpan(span); + try { + chain.doFilter(servletRequest, servletResponse); + if (!httpRequest.isAsyncStarted()) { + for (ServletFilterSpanDecorator spanDecorator : spanDecorators) { + spanDecorator.onResponse(httpRequest, httpResponse, span); + } + } + // catch all exceptions (e.g. RuntimeException, ServletException...) + } catch (Throwable ex) { + for (ServletFilterSpanDecorator spanDecorator : spanDecorators) { + spanDecorator.onError(httpRequest, httpResponse, ex, span); + } + throw ex; + } finally { + scope.close(); + + if (httpRequest.isAsyncStarted()) { + // what if async is already finished? This would not be called + httpRequest + .getAsyncContext() + .addListener( + new AsyncListener() { + @Override + public void onComplete(AsyncEvent event) throws IOException { + HttpServletRequest httpRequest = + (HttpServletRequest) event.getSuppliedRequest(); + HttpServletResponse httpResponse = + (HttpServletResponse) event.getSuppliedResponse(); + for (ServletFilterSpanDecorator spanDecorator : spanDecorators) { + spanDecorator.onResponse(httpRequest, httpResponse, span); + } + span.end(); + } + + @Override + public void onTimeout(AsyncEvent event) throws IOException { + HttpServletRequest httpRequest = + (HttpServletRequest) event.getSuppliedRequest(); + HttpServletResponse httpResponse = + (HttpServletResponse) event.getSuppliedResponse(); + for (ServletFilterSpanDecorator spanDecorator : spanDecorators) { + spanDecorator.onTimeout( + httpRequest, httpResponse, event.getAsyncContext().getTimeout(), span); + } + } + + @Override + public void onError(AsyncEvent event) throws IOException { + HttpServletRequest httpRequest = + (HttpServletRequest) event.getSuppliedRequest(); + HttpServletResponse httpResponse = + (HttpServletResponse) event.getSuppliedResponse(); + for (ServletFilterSpanDecorator spanDecorator : spanDecorators) { + spanDecorator.onError( + httpRequest, httpResponse, event.getThrowable(), span); + } + } + + @Override + public void onStartAsync(AsyncEvent event) throws IOException {} + }); + } else { + // If not async, then need to explicitly finish the span associated with the scope. + // This is necessary, as we don't know whether this request is being handled + // asynchronously until after the scope has already been started. + span.end(); + } + } + } + } + + @Override + public void destroy() {} + + /** + * It checks whether a request should be traced or not. + * + * @param httpServletRequest request + * @param httpServletResponse response + * @return whether request should be traced or not + */ + protected boolean isTraced( + HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { + // skip URLs matching skip pattern + // e.g. pattern is defined as '/health|/status' then URL 'http://localhost:5000/context/health' + // won't be traced + if (skipPattern != null) { + String url = + httpServletRequest + .getRequestURI() + .substring(httpServletRequest.getContextPath().length()); + return !skipPattern.matcher(url).matches(); + } + + return true; + } + + /** + * Get context of server span. + * + * @param servletRequest request + * @return server span context + */ + public static SpanContext serverSpanContext(ServletRequest servletRequest) { + return (SpanContext) servletRequest.getAttribute(SERVER_SPAN_CONTEXT); + } +} diff --git a/contrib/web_servlet_filter/src/main/java/io/opentelemetry/contrib/web/servlet/filter/decorator/ServletFilterHeaderSpanDecorator.java b/contrib/web_servlet_filter/src/main/java/io/opentelemetry/contrib/web/servlet/filter/decorator/ServletFilterHeaderSpanDecorator.java new file mode 100644 index 00000000000..03172c12fee --- /dev/null +++ b/contrib/web_servlet_filter/src/main/java/io/opentelemetry/contrib/web/servlet/filter/decorator/ServletFilterHeaderSpanDecorator.java @@ -0,0 +1,131 @@ +/* + * 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.contrib.web.servlet.filter.decorator; + +import io.opentelemetry.contrib.web.servlet.filter.ServletFilterSpanDecorator; +import io.opentelemetry.trace.Span; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nullable; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * ServletFilterHeaderSpanDecorator will decorate the span based on incoming HTTP headers. Incoming + * are compared to the list of {@link #allowedHeaders}, if the header is part of the provided list, + * they will be added as {@link StringTag}. The tag format will be a concatenation of {@link + * #prefix} and {@link HeaderEntry#tag} + */ +public class ServletFilterHeaderSpanDecorator implements ServletFilterSpanDecorator { + + @Nullable private final String prefix; + private final List allowedHeaders; + + /** + * Constructor of ServletFilterHeaderSpanDecorator with a default prefix of "http.header." + * + * @param allowedHeaders list of {@link HeaderEntry} to extract from the incoming request + */ + public ServletFilterHeaderSpanDecorator(List allowedHeaders) { + this(allowedHeaders, "http.header."); + } + + /** + * Constructor of ServletFilterHeaderSpanDecorator. + * + * @param allowedHeaders list of {@link HeaderEntry} to extract from the incoming request + * @param prefix the prefix to prepend on each @{@link StringTag}. Can be null is not prefix is + * desired + */ + public ServletFilterHeaderSpanDecorator(List allowedHeaders, String prefix) { + this.allowedHeaders = new ArrayList<>(allowedHeaders); + this.prefix = (prefix != null && !prefix.isEmpty()) ? prefix : null; + } + + @Override + public void onRequest(HttpServletRequest httpServletRequest, Span span) { + for (HeaderEntry headerEntry : allowedHeaders) { + String headerValue = httpServletRequest.getHeader(headerEntry.getHeader()); + if (headerValue != null && !headerValue.isEmpty()) { + span.setAttribute(buildAttrKey(headerEntry.getTag()), headerValue); + } + } + } + + @Override + public void onResponse( + HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Span span) {} + + @Override + public void onError( + HttpServletRequest httpServletRequest, + HttpServletResponse httpServletResponse, + Throwable exception, + Span span) {} + + @Override + public void onTimeout( + HttpServletRequest httpServletRequest, + HttpServletResponse httpServletResponse, + long timeout, + Span span) {} + + private String buildAttrKey(String tag) { + if (prefix == null) { + return tag; + } + return prefix + tag; + } + + @Nullable + public String getPrefix() { + return this.prefix; + } + + public List getAllowedHeaders() { + return this.allowedHeaders; + } + + /** + * HeaderEntry is used to configure {@link ServletFilterHeaderSpanDecorator} {@link #header} is + * used to check if the header exists using {@link HttpServletRequest#getHeader(String)} {@link + * #tag} will be used as a {@link StringTag} if {@link #header} is found on the incoming request. + */ + public static class HeaderEntry { + private final String header; + private final String tag; + + /** + * Summary. + * + * @param header Header on the {@link HttpServletRequest} + * @param tag Tag to be used if {@link #header} is found + */ + public HeaderEntry(String header, String tag) { + this.header = header; + this.tag = tag; + } + + public String getHeader() { + return this.header; + } + + public String getTag() { + return this.tag; + } + } +} 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 d356447a684..8d9f3dd0c41 100644 --- a/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/BaseShimObject.java +++ b/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/BaseShimObject.java @@ -16,7 +16,7 @@ package io.opentelemetry.opentracingshim; -import io.opentelemetry.distributedcontext.DistributedContextManager; +import io.opentelemetry.distributedcontext.CorrelationContextManager; import io.opentelemetry.trace.Tracer; abstract class BaseShimObject { @@ -34,7 +34,7 @@ Tracer tracer() { return telemetryInfo.tracer(); } - DistributedContextManager contextManager() { + CorrelationContextManager contextManager() { return telemetryInfo.contextManager(); } } 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 3cb18ca0b94..edcc7c56a66 100644 --- a/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java +++ b/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java @@ -46,7 +46,7 @@ public SpanContextShim extractTextFormat(TextMapExtract carrier) { io.opentelemetry.trace.SpanContext context = tracer().getHttpTextFormat().extract(carrierMap, TextMapGetter.INSTANCE); - io.opentelemetry.distributedcontext.DistributedContext distContext = + io.opentelemetry.distributedcontext.CorrelationContext distContext = contextManager().getHttpTextFormat().extract(carrierMap, TextMapGetter.INSTANCE); return new SpanContextShim(telemetryInfo, context, distContext); diff --git a/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/SpanContextShim.java b/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/SpanContextShim.java index 3e0790f94dd..fc3e396d7e6 100644 --- a/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/SpanContextShim.java +++ b/opentracing_shim/src/main/java/io/opentelemetry/opentracingshim/SpanContextShim.java @@ -16,21 +16,21 @@ package io.opentelemetry.opentracingshim; -import io.opentelemetry.distributedcontext.DistributedContext; -import io.opentelemetry.distributedcontext.Entry; -import io.opentelemetry.distributedcontext.EntryKey; -import io.opentelemetry.distributedcontext.EntryMetadata; -import io.opentelemetry.distributedcontext.EntryValue; +import io.opentelemetry.distributedcontext.CorrelationContext; +import io.opentelemetry.distributedcontext.Label; +import io.opentelemetry.distributedcontext.LabelKey; +import io.opentelemetry.distributedcontext.LabelMetadata; +import io.opentelemetry.distributedcontext.LabelValue; import io.opentracing.SpanContext; import java.util.Iterator; import java.util.Map; final class SpanContextShim extends BaseShimObject implements SpanContext { - static final EntryMetadata DEFAULT_ENTRY_METADATA = - EntryMetadata.create(EntryMetadata.EntryTtl.UNLIMITED_PROPAGATION); + static final LabelMetadata DEFAULT_ENTRY_METADATA = + LabelMetadata.create(LabelMetadata.HopLimit.UNLIMITED_PROPAGATION); private final io.opentelemetry.trace.SpanContext context; - private final DistributedContext distContext; + private final CorrelationContext distContext; public SpanContextShim(SpanShim spanShim) { this( @@ -46,15 +46,15 @@ public SpanContextShim(TelemetryInfo telemetryInfo, io.opentelemetry.trace.SpanC public SpanContextShim( TelemetryInfo telemetryInfo, io.opentelemetry.trace.SpanContext context, - DistributedContext distContext) { + CorrelationContext distContext) { super(telemetryInfo); this.context = context; this.distContext = distContext; } SpanContextShim newWithKeyValue(String key, String value) { - DistributedContext.Builder builder = contextManager().contextBuilder().setParent(distContext); - builder.put(EntryKey.create(key), EntryValue.create(value), DEFAULT_ENTRY_METADATA); + CorrelationContext.Builder builder = contextManager().contextBuilder().setParent(distContext); + builder.put(LabelKey.create(key), LabelValue.create(value), DEFAULT_ENTRY_METADATA); return new SpanContextShim(telemetryInfo(), context, builder.build()); } @@ -63,7 +63,7 @@ io.opentelemetry.trace.SpanContext getSpanContext() { return context; } - DistributedContext getDistributedContext() { + CorrelationContext getDistributedContext() { return distContext; } @@ -79,20 +79,20 @@ public String toSpanId() { @Override public Iterable> baggageItems() { - final Iterator iterator = distContext.getEntries().iterator(); + final Iterator

This is a convenience class getting and casting the telemetry objects from {@link * OpenTelemetry}. @@ -55,13 +55,13 @@ public static MeterSdk getMeter() { } /** - * Returns a {@link DistributedContextManagerSdk}. + * Returns a {@link CorrelationContextManagerSdk}. * - * @return context manager returned by {@link OpenTelemetry#getDistributedContextManager()}. + * @return context manager returned by {@link OpenTelemetry#getCorrelationContextManager()}. * @since 0.1.0 */ - public static DistributedContextManagerSdk getDistributedContextManager() { - return (DistributedContextManagerSdk) OpenTelemetry.getDistributedContextManager(); + public static CorrelationContextManagerSdk getDistributedContextManager() { + return (CorrelationContextManagerSdk) OpenTelemetry.getCorrelationContextManager(); } private OpenTelemetrySdk() {} diff --git a/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextManagerSdk.java b/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/CorrelationContextManagerSdk.java similarity index 59% rename from sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextManagerSdk.java rename to sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/CorrelationContextManagerSdk.java index acc0e9816ee..93668f5e2dc 100644 --- a/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextManagerSdk.java +++ b/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/CorrelationContextManagerSdk.java @@ -19,40 +19,40 @@ import io.opentelemetry.context.Scope; import io.opentelemetry.context.propagation.BinaryFormat; import io.opentelemetry.context.propagation.HttpTextFormat; -import io.opentelemetry.distributedcontext.DefaultDistributedContextManager; -import io.opentelemetry.distributedcontext.DistributedContext; -import io.opentelemetry.distributedcontext.DistributedContextManager; +import io.opentelemetry.distributedcontext.CorrelationContext; +import io.opentelemetry.distributedcontext.CorrelationContextManager; +import io.opentelemetry.distributedcontext.DefaultCorrelationContextManager; import io.opentelemetry.distributedcontext.unsafe.ContextUtils; /** - * {@link DistributedContextManagerSdk} is SDK implementation of {@link DistributedContextManager}. + * {@link CorrelationContextManagerSdk} is SDK implementation of {@link CorrelationContextManager}. */ -public class DistributedContextManagerSdk implements DistributedContextManager { +public class CorrelationContextManagerSdk implements CorrelationContextManager { @Override - public DistributedContext getCurrentContext() { + public CorrelationContext getCurrentContext() { return ContextUtils.getValue(); } @Override - public DistributedContext.Builder contextBuilder() { - return new DistributedContextSdk.Builder(); + public CorrelationContext.Builder contextBuilder() { + return new CorrelationContextSdk.Builder(); } @Override - public Scope withContext(DistributedContext distContext) { + public Scope withContext(CorrelationContext distContext) { return ContextUtils.withDistributedContext(distContext); } @Override - public BinaryFormat getBinaryFormat() { + public BinaryFormat getBinaryFormat() { // TODO: Implement this. - return DefaultDistributedContextManager.getInstance().getBinaryFormat(); + return DefaultCorrelationContextManager.getInstance().getBinaryFormat(); } @Override - public HttpTextFormat getHttpTextFormat() { + public HttpTextFormat getHttpTextFormat() { // TODO: Implement this. - return DefaultDistributedContextManager.getInstance().getHttpTextFormat(); + return DefaultCorrelationContextManager.getInstance().getHttpTextFormat(); } } diff --git a/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextManagerSdkProvider.java b/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/CorrelationContextManagerSdkProvider.java similarity index 70% rename from sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextManagerSdkProvider.java rename to sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/CorrelationContextManagerSdkProvider.java index a0ba4e368f3..fff4eeadb6e 100644 --- a/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextManagerSdkProvider.java +++ b/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/CorrelationContextManagerSdkProvider.java @@ -16,20 +16,20 @@ package io.opentelemetry.sdk.distributedcontext; -import io.opentelemetry.distributedcontext.DistributedContextManager; -import io.opentelemetry.distributedcontext.spi.DistributedContextManagerProvider; +import io.opentelemetry.distributedcontext.CorrelationContextManager; +import io.opentelemetry.distributedcontext.spi.CorrelationContextManagerProvider; /** * {@code DistributedContextManager} provider implementation for {@link - * io.opentelemetry.distributedcontext.spi.DistributedContextManagerProvider}. + * io.opentelemetry.distributedcontext.spi.CorrelationContextManagerProvider}. * *

This class is not intended to be used in application code and it is used only by {@link * io.opentelemetry.OpenTelemetry}. */ -public class DistributedContextManagerSdkProvider implements DistributedContextManagerProvider { +public class CorrelationContextManagerSdkProvider implements CorrelationContextManagerProvider { @Override - public DistributedContextManager create() { - return new DistributedContextManagerSdk(); + public CorrelationContextManager create() { + return new CorrelationContextManagerSdk(); } } diff --git a/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextSdk.java b/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/CorrelationContextSdk.java similarity index 66% rename from sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextSdk.java rename to sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/CorrelationContextSdk.java index bd0d61fbd81..e5e21aacb04 100644 --- a/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextSdk.java +++ b/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/CorrelationContextSdk.java @@ -19,11 +19,11 @@ import static io.opentelemetry.internal.Utils.checkNotNull; import io.opentelemetry.OpenTelemetry; -import io.opentelemetry.distributedcontext.DistributedContext; -import io.opentelemetry.distributedcontext.Entry; -import io.opentelemetry.distributedcontext.EntryKey; -import io.opentelemetry.distributedcontext.EntryMetadata; -import io.opentelemetry.distributedcontext.EntryValue; +import io.opentelemetry.distributedcontext.CorrelationContext; +import io.opentelemetry.distributedcontext.Label; +import io.opentelemetry.distributedcontext.LabelKey; +import io.opentelemetry.distributedcontext.LabelMetadata; +import io.opentelemetry.distributedcontext.LabelValue; import io.opentelemetry.internal.Utils; import java.util.Collection; import java.util.Collections; @@ -36,36 +36,36 @@ @Immutable // TODO: Migrate to AutoValue // @AutoValue -class DistributedContextSdk implements DistributedContext { +class CorrelationContextSdk implements CorrelationContext { // The types of the EntryKey and Entry must match for each entry. - private final Map entries; - @Nullable private final DistributedContext parent; + private final Map entries; + @Nullable private final CorrelationContext parent; /** - * Creates a new {@link DistributedContextSdk} with the given entries. + * Creates a new {@link CorrelationContextSdk} with the given entries. * * @param entries the initial entries for this {@code DistributedContextSdk}. * @param parent providing a default set of entries */ - private DistributedContextSdk( - Map entries, DistributedContext parent) { + private CorrelationContextSdk( + Map entries, CorrelationContext parent) { this.entries = Collections.unmodifiableMap(new HashMap<>(checkNotNull(entries, "entries"))); this.parent = parent; } @Override - public Collection getEntries() { - Map combined = new HashMap<>(entries); + public Collection

Tests for scope management with {@link DistributedContextManagerSdk} are in {@link + *

Tests for scope management with {@link CorrelationContextManagerSdk} are in {@link * ScopedDistributedContextTest}. */ @RunWith(JUnit4.class) public class DistributedContextSdkTest { - private final DistributedContextManager contextManager = new DistributedContextManagerSdk(); + private final CorrelationContextManager contextManager = new CorrelationContextManagerSdk(); - private static final EntryMetadata TMD = - EntryMetadata.create(EntryMetadata.EntryTtl.UNLIMITED_PROPAGATION); + private static final LabelMetadata TMD = + LabelMetadata.create(LabelMetadata.HopLimit.UNLIMITED_PROPAGATION); - private static final EntryKey K1 = EntryKey.create("k1"); - private static final EntryKey K2 = EntryKey.create("k2"); + private static final LabelKey K1 = LabelKey.create("k1"); + private static final LabelKey K2 = LabelKey.create("k2"); - private static final EntryValue V1 = EntryValue.create("v1"); - private static final EntryValue V2 = EntryValue.create("v2"); + private static final LabelValue V1 = LabelValue.create("v1"); + private static final LabelValue V2 = LabelValue.create("v2"); - private static final Entry T1 = Entry.create(K1, V1, TMD); - private static final Entry T2 = Entry.create(K2, V2, TMD); + private static final Label T1 = Label.create(K1, V1, TMD); + private static final Label T2 = Label.create(K2, V2, TMD); @Rule public final ExpectedException thrown = ExpectedException.none(); @Test public void getEntries_empty() { - DistributedContextSdk distContext = new DistributedContextSdk.Builder().build(); + CorrelationContextSdk distContext = new CorrelationContextSdk.Builder().build(); assertThat(distContext.getEntries()).isEmpty(); } @Test public void getEntries_nonEmpty() { - DistributedContextSdk distContext = listToDistributedContext(T1, T2); + CorrelationContextSdk distContext = listToDistributedContext(T1, T2); assertThat(distContext.getEntries()).containsExactly(T1, T2); } @Test public void getEntries_chain() { - Entry t1alt = Entry.create(K1, V2, TMD); - DistributedContextSdk parent = listToDistributedContext(T1, T2); - DistributedContext distContext = + Label t1alt = Label.create(K1, V2, TMD); + CorrelationContextSdk parent = listToDistributedContext(T1, T2); + CorrelationContext distContext = contextManager .contextBuilder() .setParent(parent) @@ -83,7 +83,7 @@ public void getEntries_chain() { @Test public void put_newKey() { - DistributedContextSdk distContext = listToDistributedContext(T1); + CorrelationContextSdk distContext = listToDistributedContext(T1); assertThat( contextManager .contextBuilder() @@ -96,7 +96,7 @@ public void put_newKey() { @Test public void put_existingKey() { - DistributedContextSdk distContext = listToDistributedContext(T1); + CorrelationContextSdk distContext = listToDistributedContext(T1); assertThat( contextManager .contextBuilder() @@ -104,13 +104,13 @@ public void put_existingKey() { .put(K1, V2, TMD) .build() .getEntries()) - .containsExactly(Entry.create(K1, V2, TMD)); + .containsExactly(Label.create(K1, V2, TMD)); } @Test public void put_nullKey() { - DistributedContextSdk distContext = listToDistributedContext(T1); - DistributedContext.Builder builder = contextManager.contextBuilder().setParent(distContext); + CorrelationContextSdk distContext = listToDistributedContext(T1); + CorrelationContext.Builder builder = contextManager.contextBuilder().setParent(distContext); thrown.expect(NullPointerException.class); thrown.expectMessage("key"); builder.put(null, V2, TMD); @@ -118,8 +118,8 @@ public void put_nullKey() { @Test public void put_nullValue() { - DistributedContextSdk distContext = listToDistributedContext(T1); - DistributedContext.Builder builder = contextManager.contextBuilder().setParent(distContext); + CorrelationContextSdk distContext = listToDistributedContext(T1); + CorrelationContext.Builder builder = contextManager.contextBuilder().setParent(distContext); thrown.expect(NullPointerException.class); thrown.expectMessage("value"); builder.put(K2, null, TMD); @@ -127,22 +127,22 @@ public void put_nullValue() { @Test public void setParent_nullValue() { - DistributedContextSdk parent = listToDistributedContext(T1); + CorrelationContextSdk parent = listToDistributedContext(T1); thrown.expect(NullPointerException.class); contextManager.contextBuilder().setParent(parent).setParent(null).build(); } @Test public void setParent_setNoParent() { - DistributedContextSdk parent = listToDistributedContext(T1); - DistributedContext distContext = + CorrelationContextSdk parent = listToDistributedContext(T1); + CorrelationContext distContext = contextManager.contextBuilder().setParent(parent).setNoParent().build(); assertThat(distContext.getEntries()).isEmpty(); } @Test public void remove_existingKey() { - DistributedContextSdk.Builder builder = new DistributedContextSdk.Builder(); + CorrelationContextSdk.Builder builder = new CorrelationContextSdk.Builder(); builder.put(T1.getKey(), T1.getValue(), T1.getEntryMetadata()); builder.put(T2.getKey(), T2.getValue(), T2.getEntryMetadata()); @@ -151,7 +151,7 @@ public void remove_existingKey() { @Test public void remove_differentKey() { - DistributedContextSdk.Builder builder = new DistributedContextSdk.Builder(); + CorrelationContextSdk.Builder builder = new CorrelationContextSdk.Builder(); builder.put(T1.getKey(), T1.getValue(), T1.getEntryMetadata()); builder.put(T2.getKey(), T2.getValue(), T2.getEntryMetadata()); @@ -160,7 +160,7 @@ public void remove_differentKey() { @Test public void remove_keyFromParent() { - DistributedContextSdk distContext = listToDistributedContext(T1, T2); + CorrelationContextSdk distContext = listToDistributedContext(T1, T2); assertThat( contextManager.contextBuilder().setParent(distContext).remove(K1).build().getEntries()) .containsExactly(T2); @@ -168,7 +168,7 @@ public void remove_keyFromParent() { @Test public void remove_nullKey() { - DistributedContext.Builder builder = contextManager.contextBuilder(); + CorrelationContext.Builder builder = contextManager.contextBuilder(); thrown.expect(NullPointerException.class); thrown.expectMessage("key"); builder.remove(null); diff --git a/sdk/src/test/java/io/opentelemetry/sdk/distributedcontext/DistributedContextTestUtil.java b/sdk/src/test/java/io/opentelemetry/sdk/distributedcontext/DistributedContextTestUtil.java index 613bfa28930..228d2b05e21 100644 --- a/sdk/src/test/java/io/opentelemetry/sdk/distributedcontext/DistributedContextTestUtil.java +++ b/sdk/src/test/java/io/opentelemetry/sdk/distributedcontext/DistributedContextTestUtil.java @@ -16,19 +16,19 @@ package io.opentelemetry.sdk.distributedcontext; -import io.opentelemetry.distributedcontext.Entry; +import io.opentelemetry.distributedcontext.Label; import java.util.Arrays; import java.util.List; class DistributedContextTestUtil { - static DistributedContextSdk listToDistributedContext(Entry... entries) { + static CorrelationContextSdk listToDistributedContext(Label... entries) { return listToDistributedContext(Arrays.asList(entries)); } - static DistributedContextSdk listToDistributedContext(List entries) { - DistributedContextSdk.Builder builder = new DistributedContextSdk.Builder(); - for (Entry entry : entries) { + static CorrelationContextSdk listToDistributedContext(List