Refactor kotlin coroutine plugin with CoroutineContext (#453)

This commit is contained in:
Kanro 2023-02-14 18:10:21 +08:00 committed by GitHub
parent 5250ecfe2e
commit bca5c8e628
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 205 additions and 494 deletions

View File

@ -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

View File

@ -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) {
}
}

View File

@ -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));
}
}
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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]);
}
}

View File

@ -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;
}
}
};
}
}

View File

@ -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;
}
}
};
}
}

View File

@ -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;
}
}
};
}
}

View File

@ -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
kotlin-coroutine=org.apache.skywalking.apm.plugin.kotlin.coroutine.define.CoroutineContextInstrumentation