diff --git a/build.gradle b/build.gradle
index 928da15cb..d1c2ad68f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -63,6 +63,7 @@ dependencies {
compile group: 'io.micrometer', name: 'micrometer-core', version: '1.1.2'
compile group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'
compile group: 'com.auth0', name: 'java-jwt', version:'3.10.2'
+ compile group: 'io.opentelemetry', name: 'opentelemetry-sdk', version: '1.1.0'
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile group: 'com.googlecode.junit-toolbox', name: 'junit-toolbox', version: '2.4'
diff --git a/src/main/java/com/uber/cadence/context/ContextPropagator.java b/src/main/java/com/uber/cadence/context/ContextPropagator.java
index 3a618f96c..d302ffdaa 100644
--- a/src/main/java/com/uber/cadence/context/ContextPropagator.java
+++ b/src/main/java/com/uber/cadence/context/ContextPropagator.java
@@ -23,6 +23,9 @@
* Context Propagators are used to propagate information from workflow to activity, workflow to
* child workflow, and workflow to child thread (using {@link com.uber.cadence.workflow.Async}).
*
+ *
It is important to note that all threads share one ContextPropagator instance, so your
+ * implementation must be thread-safe and store any state in ThreadLocal variables.
+ *
*
A sample ContextPropagator
that copies all {@link org.slf4j.MDC} entries starting
* with a given prefix along the code path looks like this:
*
@@ -136,4 +139,31 @@ public interface ContextPropagator {
/** Sets the current context */
void setCurrentContext(Object context);
+
+ /**
+ * This is a lifecycle method, called after the context has been propagated to the
+ * workflow/activity thread but the workflow/activity has not yet started.
+ */
+ default void setUp() {
+ // No-op
+ }
+
+ /**
+ * This is a lifecycle method, called after the workflow/activity has completed. If the method
+ * finished without exception, {@code successful} will be true. Otherwise, it will be false and
+ * {@link #onError(Throwable)} will have already been called.
+ */
+ default void finish() {
+ // No-op
+ }
+
+ /**
+ * This is a lifecycle method, called when the workflow/activity finishes by throwing an unhandled
+ * exception. {@link #finish()} is called after this method.
+ *
+ * @param t The unhandled exception that caused the workflow/activity to terminate
+ */
+ default void onError(Throwable t) {
+ // No-op
+ }
}
diff --git a/src/main/java/com/uber/cadence/context/OpenTelemetryContextPropagator.java b/src/main/java/com/uber/cadence/context/OpenTelemetryContextPropagator.java
new file mode 100644
index 000000000..927d3c71f
--- /dev/null
+++ b/src/main/java/com/uber/cadence/context/OpenTelemetryContextPropagator.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Modifications copyright (C) 2017 Uber Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not
+ * use this file except in compliance with the License. A copy of the License is
+ * located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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 com.uber.cadence.context;
+
+import io.opentelemetry.api.GlobalOpenTelemetry;
+import io.opentelemetry.api.baggage.Baggage;
+import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator;
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.api.trace.SpanKind;
+import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
+import io.opentelemetry.context.Context;
+import io.opentelemetry.context.Scope;
+import io.opentelemetry.context.propagation.TextMapGetter;
+import io.opentelemetry.context.propagation.TextMapPropagator;
+import io.opentelemetry.context.propagation.TextMapSetter;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.slf4j.MDC;
+
+public class OpenTelemetryContextPropagator implements ContextPropagator {
+
+ private static final TextMapPropagator w3cTraceContextPropagator =
+ W3CTraceContextPropagator.getInstance();
+ private static final TextMapPropagator w3cBaggagePropagator = W3CBaggagePropagator.getInstance();
+ private static ThreadLocal currentContextOtelScope = new ThreadLocal<>();
+ private static ThreadLocal currentOtelSpan = new ThreadLocal<>();
+ private static ThreadLocal currentOtelScope = new ThreadLocal<>();
+ private static ThreadLocal> otelKeySet = new ThreadLocal<>();
+ private static final TextMapSetter