Refactor kotlin coroutine plugin with CoroutineContext (#453)
This commit is contained in:
parent
5250ecfe2e
commit
bca5c8e628
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue