From fb7df48651db7b95d10c960d9918034082d8f567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=85=89=E6=B0=B8=20yangguangyong?= Date: Tue, 12 Apr 2022 14:01:53 +0800 Subject: [PATCH 1/9] [Feature] Add JDK ThreadPoolExecutor plugin(#8743) * it can instruct 'execute' and 'submit' method in 'ThreadPoolExecutor'. * 'ThreadPoolExecutor' and its subclasses can be instructed. --- .github/workflows/plugins-test.3.yaml | 1 + CHANGES.md | 1 + .../core/conf/SnifferConfigInitializer.java | 9 + .../core/logging/core/WriterFactory.java | 4 +- .../core/logging/core/WriterFactoryTest.java | 2 + .../skywalking/apm/agent/SkyWalkingAgent.java | 2 + .../jdk-threadpool-plugin/pom.xml | 48 +++ .../AbstractThreadingPoolInterceptor.java | 59 +++ .../ThreadPoolExecuteMethodInterceptor.java | 45 +++ .../ThreadPoolSubmitMethodInterceptor.java | 47 +++ .../ThreadPoolExecutorInstrumentation.java | 103 +++++ .../apm/plugin/wrapper/SwCallableWrapper.java | 53 +++ .../apm/plugin/wrapper/SwRunnableWrapper.java | 52 +++ .../src/main/resources/skywalking-plugin.def | 17 + apm-sniffer/bootstrap-plugins/pom.xml | 1 + .../java-agent/Bootstrap-plugins.md | 3 +- .../service-agent/java-agent/Plugin-list.md | 1 + .../jdk-threadpool-scenario/bin/startup.sh | 21 + .../config/expectedData.yaml | 372 ++++++++++++++++++ .../jdk-threadpool-scenario/configuration.yml | 22 ++ .../scenarios/jdk-threadpool-scenario/pom.xml | 88 +++++ .../src/main/assembly/assembly.xml | 41 ++ .../testcase/jdk/threading/Application.java | 110 ++++++ .../src/main/resources/application.yaml | 19 + .../support-version.list | 17 + 25 files changed, 1136 insertions(+), 2 deletions(-) create mode 100644 apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml create mode 100644 apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolExecuteMethodInterceptor.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolSubmitMethodInterceptor.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/wrapper/SwCallableWrapper.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/wrapper/SwRunnableWrapper.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/resources/skywalking-plugin.def create mode 100644 test/plugin/scenarios/jdk-threadpool-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/jdk-threadpool-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/jdk-threadpool-scenario/configuration.yml create mode 100644 test/plugin/scenarios/jdk-threadpool-scenario/pom.xml create mode 100644 test/plugin/scenarios/jdk-threadpool-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/jdk-threadpool-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/threading/Application.java create mode 100644 test/plugin/scenarios/jdk-threadpool-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/jdk-threadpool-scenario/support-version.list diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml index 1ef64b5da0..74419fcc4a 100644 --- a/.github/workflows/plugins-test.3.yaml +++ b/.github/workflows/plugins-test.3.yaml @@ -98,6 +98,7 @@ jobs: - tomcat-thread-pool-scenario - guava-eventbus-scenario - shenyu-2.4.x-scenario + - jdk-threadpool-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index 835c8ca2bc..9d24594bc8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -36,6 +36,7 @@ Release Notes. * Make sure the parent endpoint in tracing context from existing first ENTRY span, rather than first span only. * Fix the bug that maybe causing memory leak and repeated traceId when use gateway-2.1.x-plugin or gateway-3.x-plugin. * Fix Grpc 1.x plugin could leak context due to gRPC cancelled. +* Add JDK ThreadPoolExecutor Plugin. #### Documentation diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java index 0aa984dc0e..7968ebe564 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java @@ -50,6 +50,7 @@ public class SnifferConfigInitializer { private static final String ENV_KEY_PREFIX = "skywalking."; private static Properties AGENT_SETTINGS; private static boolean IS_INIT_COMPLETED = false; + private static boolean IS_PLUGIN_INIT_COMPLETED = false; /** * If the specified agent config path is set, the agent will try to locate the specified agent config. If the @@ -234,4 +235,12 @@ static void configureLogger() { LogManager.setLogResolver(new PatternLogResolver()); } } + + public static void pluginInitCompleted() { + IS_PLUGIN_INIT_COMPLETED = true; + } + + public static boolean isPluginInitCompleted() { + return IS_PLUGIN_INIT_COMPLETED; + } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java index e8adf48d2b..1f227c4124 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java @@ -35,7 +35,9 @@ public static IWriter getLogWriter() { if (WRITER != null) { return WRITER; } - if (SnifferConfigInitializer.isInitCompleted() && AgentPackagePath.isPathFound()) { + if (SnifferConfigInitializer.isInitCompleted() + && SnifferConfigInitializer.isPluginInitCompleted() + && AgentPackagePath.isPathFound()) { if (StringUtil.isEmpty(Config.Logging.DIR)) { try { Config.Logging.DIR = AgentPackagePath.getPath() + "/logs"; diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactoryTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactoryTest.java index 0cfd717ad3..cdd299a8ac 100644 --- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactoryTest.java +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactoryTest.java @@ -43,6 +43,7 @@ public void alwaysReturnSystemLogWriteWithSetLoggingDir() { PowerMockito.mockStatic(SnifferConfigInitializer.class); PowerMockito.mockStatic(AgentPackagePath.class); BDDMockito.given(SnifferConfigInitializer.isInitCompleted()).willReturn(true); + BDDMockito.given(SnifferConfigInitializer.isPluginInitCompleted()).willReturn(true); BDDMockito.given(AgentPackagePath.isPathFound()).willReturn(true); assertTrue(SnifferConfigInitializer.isInitCompleted()); @@ -58,6 +59,7 @@ public void returnFileWriterWriteWithBlankLoggingDir() { PowerMockito.mockStatic(SnifferConfigInitializer.class); PowerMockito.mockStatic(AgentPackagePath.class); BDDMockito.given(SnifferConfigInitializer.isInitCompleted()).willReturn(true); + BDDMockito.given(SnifferConfigInitializer.isPluginInitCompleted()).willReturn(true); BDDMockito.given(AgentPackagePath.isPathFound()).willReturn(true); assertTrue(SnifferConfigInitializer.isInitCompleted()); diff --git a/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java b/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java index 31d586a685..6467a4f86a 100644 --- a/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java +++ b/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java @@ -130,6 +130,8 @@ public static void premain(String agentArgs, Instrumentation instrumentation) th .with(new Listener()) .installOn(instrumentation); + SnifferConfigInitializer.pluginInitCompleted(); + try { ServiceManager.INSTANCE.boot(); } catch (Exception e) { diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml new file mode 100644 index 0000000000..d1e0cb3dbf --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml @@ -0,0 +1,48 @@ + + + + + bootstrap-plugins + org.apache.skywalking + 8.10.0-SNAPSHOT + + 4.0.0 + + apm-jdk-threadpool-plugin + jar + + apm-jdk-threadpool-plugin + http://maven.apache.org + + + UTF-8 + + + + + + + maven-deploy-plugin + + + + + \ No newline at end of file diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java new file mode 100644 index 0000000000..d981414c8b --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java @@ -0,0 +1,59 @@ +/* + * 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; + +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 abstract class AbstractThreadingPoolInterceptor implements InstanceMethodsAroundInterceptor { + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + if (!ContextManager.isActive()) { + return; + } + + if (allArguments == null || allArguments.length < 1) { + return; + } + + Object argument = allArguments[0]; + + Object updateResult = wrap(argument); + if (updateResult != null) { + allArguments[0] = updateResult; + } + } + + public abstract Object wrap(Object param); + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + if (ContextManager.isActive()) { + ContextManager.activeSpan().log(t); + } + } +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolExecuteMethodInterceptor.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolExecuteMethodInterceptor.java new file mode 100644 index 0000000000..0464bdc5d7 --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolExecuteMethodInterceptor.java @@ -0,0 +1,45 @@ +/* + * 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; + +import org.apache.skywalking.apm.plugin.wrapper.SwRunnableWrapper; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import java.util.concurrent.RunnableFuture; + +public class ThreadPoolExecuteMethodInterceptor extends AbstractThreadingPoolInterceptor { + + @Override + public Object wrap(Object param) { + if (param instanceof SwRunnableWrapper) { + return param; + } + + if (param instanceof RunnableFuture) { + return null; + } + + if (!(param instanceof Runnable)) { + return null; + } + + Runnable runnable = (Runnable) param; + return new SwRunnableWrapper(runnable, ContextManager.capture()); + } + +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolSubmitMethodInterceptor.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolSubmitMethodInterceptor.java new file mode 100644 index 0000000000..801c1e0c7d --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolSubmitMethodInterceptor.java @@ -0,0 +1,47 @@ +/* + * 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; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.plugin.wrapper.SwCallableWrapper; +import org.apache.skywalking.apm.plugin.wrapper.SwRunnableWrapper; + +import java.util.concurrent.Callable; + +public class ThreadPoolSubmitMethodInterceptor extends AbstractThreadingPoolInterceptor { + + @Override + public Object wrap(Object param) { + if (param instanceof SwRunnableWrapper || param instanceof SwCallableWrapper) { + return param; + } + + if (param instanceof Callable) { + Callable callable = (Callable) param; + return new SwCallableWrapper(callable, ContextManager.capture()); + } + + if (param instanceof Runnable) { + Runnable runnable = (Runnable) param; + return new SwRunnableWrapper(runnable, ContextManager.capture()); + } + + return null; + } +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java new file mode 100644 index 0000000000..b5cf3e83b6 --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java @@ -0,0 +1,103 @@ +/* + * 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.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; +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.StaticMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.logical.LogicalMatchOperation; + +public class ThreadPoolExecutorInstrumentation extends ClassEnhancePluginDefine { + + protected static final String ENHANCE_CLASS = "java.util.concurrent.ThreadPoolExecutor"; + + private static final String INTERCEPT_EXECUTE_METHOD = "execute"; + + private static final String INTERCEPT_SUBMIT_METHOD = "submit"; + + private static final String INTERCEPT_EXECUTE_METHOD_HANDLE = "org.apache.skywalking.apm.plugin.ThreadPoolExecuteMethodInterceptor"; + + private static final String INTERCEPT_SUBMIT_METHOD_HANDLE = "org.apache.skywalking.apm.plugin.ThreadPoolSubmitMethodInterceptor"; + + @Override + public boolean isBootstrapInstrumentation() { + return true; + } + + @Override + protected ClassMatch enhanceClass() { + return LogicalMatchOperation.or(HierarchyMatch.byHierarchyMatch(ENHANCE_CLASS), MultiClassNameMatch.byMultiClassMatch(ENHANCE_CLASS)); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named(INTERCEPT_EXECUTE_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_EXECUTE_METHOD_HANDLE; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named(INTERCEPT_SUBMIT_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_SUBMIT_METHOD_HANDLE; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + } + }; + } + + @Override + public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() { + return new StaticMethodsInterceptPoint[0]; + } + +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/wrapper/SwCallableWrapper.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/wrapper/SwCallableWrapper.java new file mode 100644 index 0000000000..4f42962daf --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/wrapper/SwCallableWrapper.java @@ -0,0 +1,53 @@ +/* + * 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.wrapper; + +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; +import java.util.concurrent.Callable; + +public class SwCallableWrapper implements Callable { + + private Callable callable; + + private ContextSnapshot contextSnapshot; + + public SwCallableWrapper(Callable callable, ContextSnapshot contextSnapshot) { + this.callable = callable; + this.contextSnapshot = contextSnapshot; + } + + @Override + public Object call() throws Exception { + AbstractSpan span = ContextManager.createLocalSpan(getOperationName()); + span.setComponent(ComponentsDefine.JDK_THREADING); + ContextManager.continued(contextSnapshot); + try { + return callable.call(); + } finally { + ContextManager.stopSpan(); + } + } + + private String getOperationName() { + return "SwCallableWrapper/" + Thread.currentThread().getName(); + } +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/wrapper/SwRunnableWrapper.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/wrapper/SwRunnableWrapper.java new file mode 100644 index 0000000000..d3bdb34d9a --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/wrapper/SwRunnableWrapper.java @@ -0,0 +1,52 @@ +/* + * 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.wrapper; + +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; + +public class SwRunnableWrapper implements Runnable { + + private Runnable runnable; + + private ContextSnapshot contextSnapshot; + + public SwRunnableWrapper(Runnable runnable, ContextSnapshot contextSnapshot) { + this.runnable = runnable; + this.contextSnapshot = contextSnapshot; + } + + @Override + public void run() { + AbstractSpan span = ContextManager.createLocalSpan(getOperationName()); + span.setComponent(ComponentsDefine.JDK_THREADING); + ContextManager.continued(contextSnapshot); + try { + runnable.run(); + } finally { + ContextManager.stopSpan(); + } + } + + private String getOperationName() { + return "SwRunnableWrapper/" + Thread.currentThread().getName(); + } +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..2162787cd1 --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,17 @@ +# 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. + +jdk-threadpool-plugin=org.apache.skywalking.apm.plugin.define.ThreadPoolExecutorInstrumentation diff --git a/apm-sniffer/bootstrap-plugins/pom.xml b/apm-sniffer/bootstrap-plugins/pom.xml index 7034b62854..b4f7f0ef86 100644 --- a/apm-sniffer/bootstrap-plugins/pom.xml +++ b/apm-sniffer/bootstrap-plugins/pom.xml @@ -44,6 +44,7 @@ jdk-http-plugin jdk-threading-plugin + jdk-threadpool-plugin diff --git a/docs/en/setup/service-agent/java-agent/Bootstrap-plugins.md b/docs/en/setup/service-agent/java-agent/Bootstrap-plugins.md index 33fbe321ff..415ebcdb23 100644 --- a/docs/en/setup/service-agent/java-agent/Bootstrap-plugins.md +++ b/docs/en/setup/service-agent/java-agent/Bootstrap-plugins.md @@ -4,4 +4,5 @@ For using these plugins, you need to put the target plugin jar file into `/plugi Now, we have the following known bootstrap plugins. * Plugin of JDK HttpURLConnection. Agent is compatible with JDK 1.8+ -* Plugin of JDK Callable and Runnable. Agent is compatible with JDK 1.8+ \ No newline at end of file +* Plugin of JDK Callable and Runnable. Agent is compatible with JDK 1.8+ +* Plugin of JDK ThreadPoolExecutor. Agent is compatible with JDK 1.8+ \ No newline at end of file diff --git a/docs/en/setup/service-agent/java-agent/Plugin-list.md b/docs/en/setup/service-agent/java-agent/Plugin-list.md index 213d86b896..442073ee66 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -137,3 +137,4 @@ - tomcat-thread-pool - guava-eventbus - shenyu-2.4.x +- jdk-threadpool-plugin diff --git a/test/plugin/scenarios/jdk-threadpool-scenario/bin/startup.sh b/test/plugin/scenarios/jdk-threadpool-scenario/bin/startup.sh new file mode 100644 index 0000000000..811fbb4ea6 --- /dev/null +++ b/test/plugin/scenarios/jdk-threadpool-scenario/bin/startup.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# +# 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. + +home="$(cd "$(dirname $0)"; pwd)" + +java -jar ${agent_opts} ${home}/../libs/jdk-threadpool-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/jdk-threadpool-scenario/config/expectedData.yaml b/test/plugin/scenarios/jdk-threadpool-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..3a78cdd075 --- /dev/null +++ b/test/plugin/scenarios/jdk-threadpool-scenario/config/expectedData.yaml @@ -0,0 +1,372 @@ +# 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. +segmentItems: + - serviceName: jdk-threadpool-scenario + segmentSize: ge 14 + segments: + - segmentId: not null + spans: + - operationName: GET:/threadpool + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/threadpool'} + - {key: http.method, value: GET} + refs: + - {parentEndpoint: SwRunnableWrapper/http-get-thread, networkAddress: 'localhost:8080', + refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: jdk-threadpool-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: /threadpool + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/threadpool'} + - {key: http.method, value: GET} + - operationName: SwRunnableWrapper/http-get-thread + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 80 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + refs: + - {parentEndpoint: 'GET:/greet/{username}', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: jdk-threadpool-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: GET:/threadpool + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/threadpool'} + - {key: http.method, value: GET} + refs: + - {parentEndpoint: SwCallableWrapper/http-get-thread, networkAddress: 'localhost:8080', + refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: jdk-threadpool-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: /threadpool + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/threadpool'} + - {key: http.method, value: GET} + - operationName: SwCallableWrapper/http-get-thread + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 80 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + refs: + - {parentEndpoint: 'GET:/greet/{username}', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: jdk-threadpool-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: GET:/threadpool + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/threadpool'} + - {key: http.method, value: GET} + refs: + - {parentEndpoint: SwRunnableWrapper/http-get-thread, networkAddress: 'localhost:8080', + refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: jdk-threadpool-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: /threadpool + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/threadpool'} + - {key: http.method, value: GET} + - operationName: SwRunnableWrapper/http-get-thread + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 80 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + refs: + - {parentEndpoint: 'GET:/greet/{username}', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: jdk-threadpool-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: /threadpool + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/threadpool'} + - {key: http.method, value: GET} + - operationName: SwRunnableWrapper/http-get-thread + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 80 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + refs: + - {parentEndpoint: 'GET:/greet/{username}', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: jdk-threadpool-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: GET:/threadpool + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/threadpool'} + - {key: http.method, value: GET} + refs: + - {parentEndpoint: SwCallableWrapper/http-get-thread, networkAddress: 'localhost:8080', + refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: jdk-threadpool-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: GET:/threadpool + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/threadpool'} + - {key: http.method, value: GET} + refs: + - {parentEndpoint: SwRunnableWrapper/http-get-thread, networkAddress: 'localhost:8080', + refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: jdk-threadpool-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: /threadpool + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/threadpool'} + - {key: http.method, value: GET} + - operationName: SwCallableWrapper/http-get-thread + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 80 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + refs: + - {parentEndpoint: 'GET:/greet/{username}', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: jdk-threadpool-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: /threadpool + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/threadpool'} + - {key: http.method, value: GET} + - operationName: SwRunnableWrapper/http-get-thread + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 80 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + refs: + - {parentEndpoint: 'GET:/greet/{username}', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: jdk-threadpool-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: GET:/greet/{username} + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/greet/skywalking'} + - {key: http.method, value: GET} + - segmentId: not null + spans: + - operationName: GET:/threadpool + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/threadpool'} + - {key: http.method, value: GET} + refs: + - {parentEndpoint: SwRunnableWrapper/http-get-thread, networkAddress: 'localhost:8080', + refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: jdk-threadpool-scenario, + traceId: not null} \ No newline at end of file diff --git a/test/plugin/scenarios/jdk-threadpool-scenario/configuration.yml b/test/plugin/scenarios/jdk-threadpool-scenario/configuration.yml new file mode 100644 index 0000000000..1b369476aa --- /dev/null +++ b/test/plugin/scenarios/jdk-threadpool-scenario/configuration.yml @@ -0,0 +1,22 @@ +# 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. + +type: jvm +entryService: http://localhost:8080/greet/skywalking +healthCheck: http://localhost:8080/healthCheck +runningMode: with_bootstrap +withPlugins: apm-jdk-threadpool-plugin-*.jar +startScript: ./bin/startup.sh diff --git a/test/plugin/scenarios/jdk-threadpool-scenario/pom.xml b/test/plugin/scenarios/jdk-threadpool-scenario/pom.xml new file mode 100644 index 0000000000..1cb62527af --- /dev/null +++ b/test/plugin/scenarios/jdk-threadpool-scenario/pom.xml @@ -0,0 +1,88 @@ + + + + 4.0.0 + + org.apache.skywalking + jdk-threadpool-scenario + 5.0.0 + + + UTF-8 + 1.8 + 2.1.6.RELEASE + + + skywalking-jdk-threadpool-scenario + + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + + + jdk-threadpool-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + 3.8.1 + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/jdk-threadpool-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/jdk-threadpool-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..36556b7813 --- /dev/null +++ b/test/plugin/scenarios/jdk-threadpool-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ./target/jdk-threadpool-scenario.jar + ./libs + 0775 + + + \ No newline at end of file diff --git a/test/plugin/scenarios/jdk-threadpool-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/threading/Application.java b/test/plugin/scenarios/jdk-threadpool-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/threading/Application.java new file mode 100644 index 0000000000..094c0aed0e --- /dev/null +++ b/test/plugin/scenarios/jdk-threadpool-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/threading/Application.java @@ -0,0 +1,110 @@ +/* + * 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 test.apache.skywalking.apm.testcase.jdk.threading; + +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + + @RestController + static class TestController { + private final RestTemplate restTemplate; + private final ExecutorService executorService; + private final ExecutorService executorService2; + + public TestController(final RestTemplate restTemplate) { + this.restTemplate = restTemplate; + this.executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r); + thread.setName("http-get-thread"); + return thread; + } + }); + this.executorService2 = Executors.newSingleThreadExecutor(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r); + thread.setName("http-get-thread"); + return thread; + } + }); + } + + @GetMapping("/healthCheck") + public String healthCheck() { + return "Success"; + } + + @GetMapping("/greet/{username}") + public String testCase(@PathVariable final String username) throws ExecutionException, InterruptedException { + Runnable runnable = new Runnable() { + @Override + public void run() { + restTemplate.getForEntity("http://localhost:8080/threadpool", String.class); + } + }; + + Callable callable = new Callable() { + @Override + public String call() { + return restTemplate.getForEntity("http://localhost:8080/threadpool", String.class).getBody(); + } + }; + + executorService.execute(runnable); + executorService.submit(runnable); + executorService.submit(callable).get(); + + executorService2.execute(runnable); + executorService2.submit(runnable); + executorService2.submit(callable).get(); + + return username; + } + + @GetMapping("/threadpool") + public String threadpool() { + return "threadpool"; + } + + } +} diff --git a/test/plugin/scenarios/jdk-threadpool-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/jdk-threadpool-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..6ff39eb8ea --- /dev/null +++ b/test/plugin/scenarios/jdk-threadpool-scenario/src/main/resources/application.yaml @@ -0,0 +1,19 @@ +# 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. + +server: + port: 8080 + diff --git a/test/plugin/scenarios/jdk-threadpool-scenario/support-version.list b/test/plugin/scenarios/jdk-threadpool-scenario/support-version.list new file mode 100644 index 0000000000..feef03cdea --- /dev/null +++ b/test/plugin/scenarios/jdk-threadpool-scenario/support-version.list @@ -0,0 +1,17 @@ +# 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. + +all \ No newline at end of file From 2a6e46931b98d924163678ee2e187dca9729c2b2 Mon Sep 17 00:00:00 2001 From: Cool-Coding Date: Tue, 12 Apr 2022 14:42:42 +0800 Subject: [PATCH 2/9] Update apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 吴晟 Wu Sheng --- .../apm/plugin/define/ThreadPoolExecutorInstrumentation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java index b5cf3e83b6..3b5b014536 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java @@ -32,7 +32,7 @@ public class ThreadPoolExecutorInstrumentation extends ClassEnhancePluginDefine { - protected static final String ENHANCE_CLASS = "java.util.concurrent.ThreadPoolExecutor"; + private static final String ENHANCE_CLASS = "java.util.concurrent.ThreadPoolExecutor"; private static final String INTERCEPT_EXECUTE_METHOD = "execute"; From e64ebe5b61c336f35d4fcb9617ffebf65ca52ce3 Mon Sep 17 00:00:00 2001 From: Cool-Coding Date: Tue, 12 Apr 2022 14:51:40 +0800 Subject: [PATCH 3/9] Update apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 吴晟 Wu Sheng --- .../apm/plugin/define/ThreadPoolExecutorInstrumentation.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java index 3b5b014536..2bb3690168 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java @@ -95,9 +95,5 @@ public boolean isOverrideArgs() { }; } - @Override - public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() { - return new StaticMethodsInterceptPoint[0]; - } } From 2f58f02f0b6ab2bba0ebbe11518e6a773dbd2b7d Mon Sep 17 00:00:00 2001 From: Cool-Coding Date: Tue, 12 Apr 2022 14:54:27 +0800 Subject: [PATCH 4/9] Update apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 吴晟 Wu Sheng --- .../apm/plugin/define/ThreadPoolExecutorInstrumentation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java index 2bb3690168..ce8b848544 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java @@ -30,7 +30,7 @@ import org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch; import org.apache.skywalking.apm.agent.core.plugin.match.logical.LogicalMatchOperation; -public class ThreadPoolExecutorInstrumentation extends ClassEnhancePluginDefine { +public class ThreadPoolExecutorInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { private static final String ENHANCE_CLASS = "java.util.concurrent.ThreadPoolExecutor"; From 52f7096d0389c1920b32740914a494eb8662df02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=85=89=E6=B0=B8=20yangguangyong?= Date: Tue, 12 Apr 2022 15:19:15 +0800 Subject: [PATCH 5/9] 1. add comment for wrap method. 2. return null if not wrap --- .../apm/plugin/AbstractThreadingPoolInterceptor.java | 5 +++++ .../apm/plugin/ThreadPoolExecuteMethodInterceptor.java | 2 +- .../apm/plugin/ThreadPoolSubmitMethodInterceptor.java | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java index d981414c8b..d25695faa4 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java @@ -43,6 +43,11 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } } + /** + * wrap the Callable or Runnable object if needed + * @param param Callable or Runnable object + * @return Wrapped object or null if not needed to wrap + */ public abstract Object wrap(Object param); @Override diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolExecuteMethodInterceptor.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolExecuteMethodInterceptor.java index 0464bdc5d7..077d925bd6 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolExecuteMethodInterceptor.java +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolExecuteMethodInterceptor.java @@ -27,7 +27,7 @@ public class ThreadPoolExecuteMethodInterceptor extends AbstractThreadingPoolInt @Override public Object wrap(Object param) { if (param instanceof SwRunnableWrapper) { - return param; + return null; } if (param instanceof RunnableFuture) { diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolSubmitMethodInterceptor.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolSubmitMethodInterceptor.java index 801c1e0c7d..bb938dddbf 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolSubmitMethodInterceptor.java +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPoolSubmitMethodInterceptor.java @@ -29,7 +29,7 @@ public class ThreadPoolSubmitMethodInterceptor extends AbstractThreadingPoolInte @Override public Object wrap(Object param) { if (param instanceof SwRunnableWrapper || param instanceof SwCallableWrapper) { - return param; + return null; } if (param instanceof Callable) { From 22ef08cf84ea76fdb9797f027478d5b440c6efa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=85=89=E6=B0=B8=20yangguangyong?= Date: Tue, 12 Apr 2022 15:36:07 +0800 Subject: [PATCH 6/9] delete unused imports --- .../apm/plugin/define/ThreadPoolExecutorInstrumentation.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java index ce8b848544..d057a8f317 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPoolExecutorInstrumentation.java @@ -23,8 +23,7 @@ import net.bytebuddy.matcher.ElementMatchers; 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.StaticMethodsInterceptPoint; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassEnhancePluginDefine; +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 org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch; @@ -94,6 +93,4 @@ public boolean isOverrideArgs() { } }; } - - } From 5b958cd24d217ee415e04d802a696f3b4ac2d35e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=85=89=E6=B0=B8=20yangguangyong?= Date: Tue, 12 Apr 2022 15:40:40 +0800 Subject: [PATCH 7/9] delete 'ContextManager.isActive()' judgement in 'handleMethodException' method. Because normally, it must be active --- .../apm/plugin/AbstractThreadingPoolInterceptor.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java index d25695faa4..77a729691c 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java @@ -57,8 +57,6 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { - if (ContextManager.isActive()) { - ContextManager.activeSpan().log(t); - } + ContextManager.activeSpan().log(t); } } From 2f0f26326883def80520c6f989f5a8739992517b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=85=89=E6=B0=B8=20yangguangyong?= Date: Tue, 12 Apr 2022 16:29:45 +0800 Subject: [PATCH 8/9] modify the variable name of the wrap method result --- .../apm/plugin/AbstractThreadingPoolInterceptor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java index 77a729691c..c130c2f5b4 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/src/main/java/org/apache/skywalking/apm/plugin/AbstractThreadingPoolInterceptor.java @@ -37,9 +37,9 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr Object argument = allArguments[0]; - Object updateResult = wrap(argument); - if (updateResult != null) { - allArguments[0] = updateResult; + Object wrappedObject = wrap(argument); + if (wrappedObject != null) { + allArguments[0] = wrappedObject; } } From 266a6b098245d1f874575ecf0963a044c42a6d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=85=89=E6=B0=B8=20yangguangyong?= Date: Tue, 12 Apr 2022 17:55:28 +0800 Subject: [PATCH 9/9] move the 'IS_PLUGIN_INIT_COMPLETED' field to 'PluginFinder' --- .../apm/agent/core/conf/SnifferConfigInitializer.java | 9 --------- .../apm/agent/core/logging/core/WriterFactory.java | 3 ++- .../skywalking/apm/agent/core/plugin/PluginFinder.java | 9 +++++++++ .../apm/agent/core/logging/core/WriterFactoryTest.java | 10 ++++++++-- .../apache/skywalking/apm/agent/SkyWalkingAgent.java | 2 +- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java index 7968ebe564..0aa984dc0e 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java @@ -50,7 +50,6 @@ public class SnifferConfigInitializer { private static final String ENV_KEY_PREFIX = "skywalking."; private static Properties AGENT_SETTINGS; private static boolean IS_INIT_COMPLETED = false; - private static boolean IS_PLUGIN_INIT_COMPLETED = false; /** * If the specified agent config path is set, the agent will try to locate the specified agent config. If the @@ -235,12 +234,4 @@ static void configureLogger() { LogManager.setLogResolver(new PatternLogResolver()); } } - - public static void pluginInitCompleted() { - IS_PLUGIN_INIT_COMPLETED = true; - } - - public static boolean isPluginInitCompleted() { - return IS_PLUGIN_INIT_COMPLETED; - } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java index 1f227c4124..a835e8cb0d 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactory.java @@ -22,6 +22,7 @@ import org.apache.skywalking.apm.agent.core.boot.AgentPackagePath; import org.apache.skywalking.apm.agent.core.conf.Config; import org.apache.skywalking.apm.agent.core.conf.SnifferConfigInitializer; +import org.apache.skywalking.apm.agent.core.plugin.PluginFinder; import org.apache.skywalking.apm.util.StringUtil; public class WriterFactory { @@ -36,7 +37,7 @@ public static IWriter getLogWriter() { return WRITER; } if (SnifferConfigInitializer.isInitCompleted() - && SnifferConfigInitializer.isPluginInitCompleted() + && PluginFinder.isPluginInitCompleted() && AgentPackagePath.isPathFound()) { if (StringUtil.isEmpty(Config.Logging.DIR)) { try { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginFinder.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginFinder.java index 6a2082ae3f..4ef608dccc 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginFinder.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginFinder.java @@ -43,6 +43,7 @@ public class PluginFinder { private final Map> nameMatchDefine = new HashMap>(); private final List signatureMatchDefine = new ArrayList(); private final List bootstrapClassMatchDefine = new ArrayList(); + private static boolean IS_PLUGIN_INIT_COMPLETED = false; public PluginFinder(List plugins) { for (AbstractClassEnhancePluginDefine plugin : plugins) { @@ -107,4 +108,12 @@ public boolean matches(NamedElement target) { public List getBootstrapClassMatchDefine() { return bootstrapClassMatchDefine; } + + public static void pluginInitCompleted() { + IS_PLUGIN_INIT_COMPLETED = true; + } + + public static boolean isPluginInitCompleted() { + return IS_PLUGIN_INIT_COMPLETED; + } } diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactoryTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactoryTest.java index cdd299a8ac..cc3620a6e3 100644 --- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactoryTest.java +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/WriterFactoryTest.java @@ -21,6 +21,7 @@ import org.apache.skywalking.apm.agent.core.boot.AgentPackagePath; import org.apache.skywalking.apm.agent.core.conf.Config; import org.apache.skywalking.apm.agent.core.conf.SnifferConfigInitializer; +import org.apache.skywalking.apm.agent.core.plugin.PluginFinder; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.BDDMockito; @@ -33,6 +34,7 @@ @RunWith(PowerMockRunner.class) @PrepareForTest(value = { SnifferConfigInitializer.class, + PluginFinder.class, AgentPackagePath.class }) public class WriterFactoryTest { @@ -41,12 +43,14 @@ public class WriterFactoryTest { public void alwaysReturnSystemLogWriteWithSetLoggingDir() { Config.Logging.OUTPUT = LogOutput.CONSOLE; PowerMockito.mockStatic(SnifferConfigInitializer.class); + PowerMockito.mockStatic(PluginFinder.class); PowerMockito.mockStatic(AgentPackagePath.class); BDDMockito.given(SnifferConfigInitializer.isInitCompleted()).willReturn(true); - BDDMockito.given(SnifferConfigInitializer.isPluginInitCompleted()).willReturn(true); + BDDMockito.given(PluginFinder.isPluginInitCompleted()).willReturn(true); BDDMockito.given(AgentPackagePath.isPathFound()).willReturn(true); assertTrue(SnifferConfigInitializer.isInitCompleted()); + assertTrue(PluginFinder.isPluginInitCompleted()); assertTrue(AgentPackagePath.isPathFound()); IWriter logWriter = WriterFactory.getLogWriter(); @@ -57,12 +61,14 @@ public void alwaysReturnSystemLogWriteWithSetLoggingDir() { public void returnFileWriterWriteWithBlankLoggingDir() { Config.Logging.OUTPUT = LogOutput.FILE; PowerMockito.mockStatic(SnifferConfigInitializer.class); + PowerMockito.mockStatic(PluginFinder.class); PowerMockito.mockStatic(AgentPackagePath.class); BDDMockito.given(SnifferConfigInitializer.isInitCompleted()).willReturn(true); - BDDMockito.given(SnifferConfigInitializer.isPluginInitCompleted()).willReturn(true); + BDDMockito.given(PluginFinder.isPluginInitCompleted()).willReturn(true); BDDMockito.given(AgentPackagePath.isPathFound()).willReturn(true); assertTrue(SnifferConfigInitializer.isInitCompleted()); + assertTrue(PluginFinder.isPluginInitCompleted()); assertTrue(AgentPackagePath.isPathFound()); IWriter logWriter = WriterFactory.getLogWriter(); diff --git a/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java b/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java index 6467a4f86a..57a11e9f3c 100644 --- a/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java +++ b/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java @@ -130,7 +130,7 @@ public static void premain(String agentArgs, Instrumentation instrumentation) th .with(new Listener()) .installOn(instrumentation); - SnifferConfigInitializer.pluginInitCompleted(); + PluginFinder.pluginInitCompleted(); try { ServiceManager.INSTANCE.boot();