You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2023/02/14 10:10:28 UTC

[skywalking-java] branch main updated: Refactor kotlin coroutine plugin with CoroutineContext (#453)

This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-java.git


The following commit(s) were added to refs/heads/main by this push:
     new bca5c8e628 Refactor kotlin coroutine plugin with CoroutineContext (#453)
bca5c8e628 is described below

commit bca5c8e628ebacf6ab3d3962f0965d3aad9fc007
Author: Kanro <hi...@live.cn>
AuthorDate: Tue Feb 14 18:10:21 2023 +0800

    Refactor kotlin coroutine plugin with CoroutineContext (#453)
---
 CHANGES.md                                         |  2 +-
 .../DispatchedTaskExceptionInterceptor.java        | 60 ---------------
 .../coroutine/DispatchedTaskRunInterceptor.java    | 73 ------------------
 .../kotlin/coroutine/DispatcherInterceptor.java    | 56 --------------
 .../coroutine/NewCoroutineContextInterceptor.java  | 51 +++++++++++++
 .../kotlin/coroutine/TracingCoroutineContext.java  | 87 ++++++++++++++++++++++
 .../plugin/kotlin/coroutine/TracingRunnable.java   | 82 --------------------
 .../apm/plugin/kotlin/coroutine/Utils.java         | 65 ----------------
 .../define/CoroutineContextInstrumentation.java    | 65 ++++++++++++++++
 .../define/DispatchedTaskInstrumentation.java      | 86 ---------------------
 .../define/DispatcherInstrumentation.java          | 69 -----------------
 .../src/main/resources/skywalking-plugin.def       |  3 +-
 12 files changed, 205 insertions(+), 494 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index cda54595a7..e0a9a6bc76 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -12,8 +12,8 @@ Release Notes.
 * Remove Powermock entirely from the test cases.
 * Fix H2 instrumentation point
 * Refactor pipeline in jedis-plugin.
-* Enhance kotlin coroutine plugin for stack tracing.
 * Add plugin to support ClickHouse JDBC driver (0.3.2.*).
+* Refactor kotlin coroutine plugin with CoroutineContext.
 * Fix OracleURLParser ignoring actual port when :SID is absent.
 
 #### Documentation
diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/DispatchedTaskExceptionInterceptor.java b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/DispatchedTaskExceptionInterceptor.java
deleted file mode 100644
index 54395236c7..0000000000
--- a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/DispatchedTaskExceptionInterceptor.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.kotlin.coroutine;
-
-import org.apache.skywalking.apm.agent.core.context.ContextManager;
-import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-
-public class DispatchedTaskExceptionInterceptor implements InstanceMethodsAroundInterceptor {
-
-    @Override
-    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) {
-    }
-
-    @Override
-    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) {
-        if (!(ret instanceof Throwable)) return ret;
-        Throwable exception = (Throwable) ret;
-
-        if (ContextManager.isActive() && objInst.getSkyWalkingDynamicField() instanceof AbstractSpan) {
-            AbstractSpan span = (AbstractSpan) objInst.getSkyWalkingDynamicField();
-            String[] elements = Utils.getCoroutineStackTraceElements(objInst);
-            if (elements.length > 0) {
-                Map<String, String> eventMap = new HashMap<>();
-                eventMap.put("coroutine.stack", String.join("\n", elements));
-                span.log(System.currentTimeMillis(), eventMap);
-            }
-
-            objInst.setSkyWalkingDynamicField(exception);
-            span.errorOccurred().log(exception);
-        }
-        return ret;
-    }
-
-    @Override
-    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
-    }
-}
diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/DispatchedTaskRunInterceptor.java b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/DispatchedTaskRunInterceptor.java
deleted file mode 100644
index 83c4d312c8..0000000000
--- a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/DispatchedTaskRunInterceptor.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.kotlin.coroutine;
-
-import org.apache.skywalking.apm.agent.core.context.ContextManager;
-import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
-import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
-
-import java.lang.reflect.Method;
-
-public class DispatchedTaskRunInterceptor implements InstanceMethodsAroundInterceptor {
-
-    @Override
-    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) {
-        if (objInst.getSkyWalkingDynamicField() instanceof ContextSnapshot) {
-            ContextSnapshot snapshot = (ContextSnapshot) objInst.getSkyWalkingDynamicField();
-
-            if (ContextManager.isActive() && snapshot.isFromCurrent()) {
-                // Thread not switched, skip restore snapshot.
-                return;
-            }
-
-            // Create local coroutine span
-            AbstractSpan span = ContextManager.createLocalSpan(TracingRunnable.COROUTINE);
-            span.setComponent(ComponentsDefine.KT_COROUTINE);
-            objInst.setSkyWalkingDynamicField(span);
-
-            // Recover with snapshot
-            ContextManager.continued(snapshot);
-        }
-    }
-
-    @Override
-    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) {
-        if (ContextManager.isActive() && objInst.getSkyWalkingDynamicField() instanceof AbstractSpan) {
-            AbstractSpan span = (AbstractSpan) objInst.getSkyWalkingDynamicField();
-            if (span != null) {
-                ContextManager.stopSpan(span);
-            }
-        }
-        return ret;
-    }
-
-    @Override
-    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
-        if (ContextManager.isActive() && objInst.getSkyWalkingDynamicField() instanceof AbstractSpan) {
-            AbstractSpan span = (AbstractSpan) objInst.getSkyWalkingDynamicField();
-            if (span != null) {
-                ContextManager.stopSpan(span.errorOccurred().log(t));
-            }
-        }
-    }
-}
diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/DispatcherInterceptor.java b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/DispatcherInterceptor.java
deleted file mode 100644
index cc31f47e89..0000000000
--- a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/DispatcherInterceptor.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.kotlin.coroutine;
-
-import org.apache.skywalking.apm.agent.core.context.ContextManager;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-
-import java.lang.reflect.Method;
-
-public class DispatcherInterceptor implements InstanceMethodsAroundInterceptor {
-
-    @Override
-    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) {
-        if (!ContextManager.isActive()) {
-            return;
-        }
-
-        Runnable runnable = (Runnable) allArguments[1];
-
-        if (Utils.isDispatchedTask(runnable)) {
-            // Using instrumentation for DispatchedContinuation
-            EnhancedInstance enhancedRunnable = (EnhancedInstance) runnable;
-            enhancedRunnable.setSkyWalkingDynamicField(ContextManager.capture());
-        } else {
-            // Wrapping runnable with current context snapshot
-            allArguments[1] = TracingRunnable.wrapOrNot(runnable);
-        }
-    }
-
-    @Override
-    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) {
-        return ret;
-    }
-
-    @Override
-    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
-    }
-}
diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/NewCoroutineContextInterceptor.java b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/NewCoroutineContextInterceptor.java
new file mode 100644
index 0000000000..ab8b41ddee
--- /dev/null
+++ b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/NewCoroutineContextInterceptor.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.kotlin.coroutine;
+
+import kotlin.coroutines.CoroutineContext;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.StaticMethodsAroundInterceptorV2;
+
+import java.lang.reflect.Method;
+
+public class NewCoroutineContextInterceptor implements StaticMethodsAroundInterceptorV2 {
+
+    @Override
+    public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes, MethodInvocationContext context) {
+
+    }
+
+    @Override
+    public Object afterMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes, Object ret, MethodInvocationContext context) {
+        if (ContextManager.isActive()) {
+            // Create TracingCoroutineContext when have been in tracing context already.
+            // Kotlin coroutine plugin does not automatically activate tracing.
+            CoroutineContext coroutineContext = (CoroutineContext) ret;
+            // Provide context snapshot for current tracing to TracingCoroutineContext.
+            return coroutineContext.plus(new TracingCoroutineContext(ContextManager.capture()));
+        }
+
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes, Throwable t, MethodInvocationContext context) {
+    }
+}
diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/TracingCoroutineContext.java b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/TracingCoroutineContext.java
new file mode 100644
index 0000000000..84b638a888
--- /dev/null
+++ b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/TracingCoroutineContext.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.kotlin.coroutine;
+
+import kotlin.coroutines.AbstractCoroutineContextElement;
+import kotlin.coroutines.CoroutineContext;
+import kotlinx.coroutines.ThreadContextElement;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.logging.api.ILog;
+import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.jetbrains.annotations.NotNull;
+
+public class TracingCoroutineContext extends AbstractCoroutineContextElement implements ThreadContextElement<AbstractSpan> {
+    private static class Key implements CoroutineContext.Key<TracingCoroutineContext> {
+        public static final Key INSTANCE = new Key();
+
+        private Key() {
+        }
+    }
+
+    private static final String COROUTINE_OPERATION = "Kotlin/Coroutine";
+
+    private static final ILog LOG = LogManager.getLogger(TracingCoroutineContext.class);
+
+    private final ContextSnapshot snapshot;
+
+    public TracingCoroutineContext(ContextSnapshot snapshot) {
+        super(Key.INSTANCE);
+        this.snapshot = snapshot;
+    }
+
+    @Override
+    public void restoreThreadContext(@NotNull CoroutineContext coroutineContext, AbstractSpan span) {
+        if (ContextManager.isActive() && span != null) {
+            ContextManager.stopSpan(span);
+        }
+    }
+
+    @Override
+    public AbstractSpan updateThreadContext(@NotNull CoroutineContext coroutineContext) {
+        // Coroutine will be executed in a new thread, we need recover our tracing context in this thread.
+
+        // Snapshot is null means tracing is disabled in current coroutine.
+        if (snapshot != null) {
+
+            // Tracing is enabled on the target dispatched thread.
+            if (ContextManager.isActive()) {
+
+                // If the trace context is from the snapshot, it means that the thread has not been switched,
+                // and there is no need to create a cross-thread span.
+                // If not, it means that we are scheduled to a dirty thread, we log a warning and give up to
+                // create cross-thread span.
+                if (!snapshot.isFromCurrent()) {
+                    LOG.warn("Kotlin coroutine has been dispatched to a dirty thread which with active span: {}.", ContextManager.getGlobalTraceId());
+                }
+                return null;
+            }
+
+            AbstractSpan span = ContextManager.createLocalSpan(COROUTINE_OPERATION);
+            span.setComponent(ComponentsDefine.KT_COROUTINE);
+            // Recover with snapshot
+            ContextManager.continued(snapshot);
+            return span;
+        }
+
+        return null;
+    }
+}
diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/TracingRunnable.java b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/TracingRunnable.java
deleted file mode 100644
index 8fb09e9a16..0000000000
--- a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/TracingRunnable.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.kotlin.coroutine;
-
-import org.apache.skywalking.apm.agent.core.context.ContextManager;
-import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
-import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
-import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
-
-/**
- * {@link Runnable} wrapper with trace context snapshot, it will create span with context snapshot around {@link
- * Runnable} runs.
- * <p>
- * A class implementation will be cheaper cost than lambda with captured variables implementation.
- */
-class TracingRunnable implements Runnable {
-    public static final String COROUTINE = "Kotlin/Coroutine";
-
-    private ContextSnapshot snapshot;
-    private Runnable delegate;
-
-    private TracingRunnable(ContextSnapshot snapshot, Runnable delegate) {
-        this.snapshot = snapshot;
-        this.delegate = delegate;
-    }
-
-    /**
-     * Wrap {@link Runnable} by {@link TracingRunnable} if active trace context existed.
-     *
-     * @param delegate {@link Runnable} to wrap.
-     * @return Wrapped {@link TracingRunnable} or original {@link Runnable} if trace context not existed.
-     */
-    public static Runnable wrapOrNot(Runnable delegate) {
-        // Just wrap continuation with active trace context
-        if (ContextManager.isActive() && !(delegate instanceof TracingRunnable)) {
-            return new TracingRunnable(ContextManager.capture(), delegate);
-        } else {
-            return delegate;
-        }
-    }
-
-    @Override
-    public void run() {
-        if (ContextManager.isActive() && snapshot.isFromCurrent()) {
-            // Thread not switched, skip restore snapshot.
-            delegate.run();
-            return;
-        }
-
-        // Create local coroutine span
-        AbstractSpan span = ContextManager.createLocalSpan(COROUTINE);
-        span.setComponent(ComponentsDefine.KT_COROUTINE);
-
-        // Recover with snapshot
-        ContextManager.continued(snapshot);
-
-        try {
-            delegate.run();
-        } catch (Throwable e) {
-            span.errorOccurred().log(e);
-            throw e;
-        } finally {
-            ContextManager.stopSpan(span);
-        }
-    }
-}
diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/Utils.java b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/Utils.java
deleted file mode 100644
index 6698b63ae1..0000000000
--- a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/Utils.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.kotlin.coroutine;
-
-import kotlin.coroutines.jvm.internal.CoroutineStackFrame;
-import org.apache.skywalking.apm.plugin.kotlin.coroutine.define.DispatchedTaskInstrumentation;
-
-import java.util.ArrayList;
-
-public class Utils {
-    private static Class<?> DISPATCHED_TASK_CLASS = null;
-    private static Boolean IS_DISPATCHED_TASK_CLASS_LOADED = false;
-
-    private static void loadDispatchedTaskClass() {
-        if (IS_DISPATCHED_TASK_CLASS_LOADED) return;
-        try {
-            DISPATCHED_TASK_CLASS = Class.forName(DispatchedTaskInstrumentation.ENHANCE_CLASS);
-        } catch (ClassNotFoundException ignored) {
-        } finally {
-            IS_DISPATCHED_TASK_CLASS_LOADED = true;
-        }
-    }
-
-    public static boolean isDispatchedTask(Runnable runnable) {
-        loadDispatchedTaskClass();
-        if (DISPATCHED_TASK_CLASS == null) return false;
-        return DISPATCHED_TASK_CLASS.isAssignableFrom(runnable.getClass());
-    }
-
-    public static String[] getCoroutineStackTraceElements(Object runnable) {
-        if (!(runnable instanceof CoroutineStackFrame)) {
-            return new String[0];
-        }
-
-        ArrayList<String> elements = new ArrayList<>();
-        CoroutineStackFrame frame = (CoroutineStackFrame) runnable;
-        while (frame != null) {
-            StackTraceElement element = frame.getStackTraceElement();
-            frame = frame.getCallerFrame();
-
-            if (element != null) {
-                elements.add(element.toString());
-            } else {
-                elements.add("Unknown Source");
-            }
-        }
-        return elements.toArray(new String[0]);
-    }
-}
diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/define/CoroutineContextInstrumentation.java b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/define/CoroutineContextInstrumentation.java
new file mode 100644
index 0000000000..caf59a29eb
--- /dev/null
+++ b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/define/CoroutineContextInstrumentation.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.kotlin.coroutine.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.ClassStaticMethodsEnhancePluginDefineV2;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.StaticMethodsInterceptV2Point;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+public class CoroutineContextInstrumentation extends ClassStaticMethodsEnhancePluginDefineV2 {
+    public static final String ENHANCE_CLASS = "kotlinx.coroutines.CoroutineContextKt";
+    public static final String COROUTINE_CONTEXT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.kotlin.coroutine.NewCoroutineContextInterceptor";
+    public static final String ENHANCE_METHOD_NEW_COROUTINE_CONTEXT = "newCoroutineContext";
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return byName(ENHANCE_CLASS);
+    }
+
+    @Override
+    public StaticMethodsInterceptV2Point[] getStaticMethodsInterceptV2Points() {
+        return new StaticMethodsInterceptV2Point[]{
+                new StaticMethodsInterceptV2Point() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        // This matcher will match the following method:
+                        // 1. CoroutineScope.newCoroutineContext(CoroutineContext)
+                        // 2. CoroutineContext.newCoroutineContext(CoroutineContext)
+                        return named(ENHANCE_METHOD_NEW_COROUTINE_CONTEXT).and(takesArguments(2));
+                    }
+
+                    @Override
+                    public String getMethodsInterceptorV2() {
+                        return COROUTINE_CONTEXT_INTERCEPTOR_CLASS;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                }
+        };
+    }
+}
diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/define/DispatchedTaskInstrumentation.java b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/define/DispatchedTaskInstrumentation.java
deleted file mode 100644
index 62177e2c68..0000000000
--- a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/define/DispatchedTaskInstrumentation.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.kotlin.coroutine.define;
-
-import net.bytebuddy.description.method.MethodDescription;
-import net.bytebuddy.matcher.ElementMatcher;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
-import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
-
-import static net.bytebuddy.matcher.ElementMatchers.named;
-import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments;
-import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
-
-public class DispatchedTaskInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
-    public static final String ENHANCE_CLASS = "kotlinx.coroutines.DispatchedTask";
-    public static final String RUN_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.kotlin.coroutine.DispatchedTaskRunInterceptor";
-    public static final String ENHANCE_METHOD_RUN = "run";
-    public static final String EXCEPTION_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.kotlin.coroutine.DispatchedTaskExceptionInterceptor";
-    public static final String ENHANCE_METHOD_GET_EXCEPTIONAL_RESULT = "getExceptionalResult$kotlinx_coroutines_core";
-
-    @Override
-    protected ClassMatch enhanceClass() {
-        return byName(ENHANCE_CLASS);
-    }
-
-    @Override
-    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
-        return new ConstructorInterceptPoint[0];
-    }
-
-    @Override
-    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
-        return new InstanceMethodsInterceptPoint[]{
-                new InstanceMethodsInterceptPoint() {
-                    @Override
-                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
-                        return named(ENHANCE_METHOD_RUN).and(takesNoArguments());
-                    }
-
-                    @Override
-                    public String getMethodsInterceptor() {
-                        return RUN_INTERCEPTOR_CLASS;
-                    }
-
-                    @Override
-                    public boolean isOverrideArgs() {
-                        return true;
-                    }
-                },
-                new InstanceMethodsInterceptPoint() {
-                    @Override
-                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
-                        return named(ENHANCE_METHOD_GET_EXCEPTIONAL_RESULT);
-                    }
-
-                    @Override
-                    public String getMethodsInterceptor() {
-                        return EXCEPTION_INTERCEPTOR_CLASS;
-                    }
-
-                    @Override
-                    public boolean isOverrideArgs() {
-                        return false;
-                    }
-                }
-        };
-    }
-}
diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/define/DispatcherInstrumentation.java b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/define/DispatcherInstrumentation.java
deleted file mode 100644
index 0931a8b92d..0000000000
--- a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/java/org/apache/skywalking/apm/plugin/kotlin/coroutine/define/DispatcherInstrumentation.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.kotlin.coroutine.define;
-
-import net.bytebuddy.description.method.MethodDescription;
-import net.bytebuddy.matcher.ElementMatcher;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
-import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
-import org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch;
-
-import static net.bytebuddy.matcher.ElementMatchers.named;
-import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType;
-
-public class DispatcherInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
-    public static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.kotlin.coroutine.DispatcherInterceptor";
-    public static final String ENHANCE_CLASS = "kotlinx.coroutines.CoroutineDispatcher";
-    public static final String ENHANCE_METHOD_DISPATCH = "dispatch";
-
-    @Override
-    protected ClassMatch enhanceClass() {
-        return HierarchyMatch.byHierarchyMatch(ENHANCE_CLASS);
-    }
-
-    @Override
-    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
-        return new ConstructorInterceptPoint[0];
-    }
-
-    @Override
-    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
-        return new InstanceMethodsInterceptPoint[] {
-            new InstanceMethodsInterceptPoint() {
-                @Override
-                public ElementMatcher<MethodDescription> getMethodsMatcher() {
-                    return named(ENHANCE_METHOD_DISPATCH).and(takesArgumentWithType(0, "kotlin.coroutines.CoroutineContext"))
-                                                         .and(takesArgumentWithType(1, "java.lang.Runnable"));
-                }
-
-                @Override
-                public String getMethodsInterceptor() {
-                    return INTERCEPTOR_CLASS;
-                }
-
-                @Override
-                public boolean isOverrideArgs() {
-                    return true;
-                }
-            }
-        };
-    }
-}
diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/resources/skywalking-plugin.def
index 1cb46e0789..212d6297bf 100644
--- a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/resources/skywalking-plugin.def
+++ b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/src/main/resources/skywalking-plugin.def
@@ -14,5 +14,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-kotlin-coroutine=org.apache.skywalking.apm.plugin.kotlin.coroutine.define.DispatcherInstrumentation
-kotlin-coroutine=org.apache.skywalking.apm.plugin.kotlin.coroutine.define.DispatchedTaskInstrumentation
\ No newline at end of file
+kotlin-coroutine=org.apache.skywalking.apm.plugin.kotlin.coroutine.define.CoroutineContextInstrumentation
\ No newline at end of file